Gym - 101981M The 2018 ICPC Asia Nanjing Regional Contest M.Mediocre String Problem Manacher+扩增KMP

题面

题意:给你2个串(长度1e6),在第一个串里找“s1s2s3”,第二个串里找“s4”,拼接后,是一个回文串,求方案数

题解:知道s1和s4回文,s2和s3回文,所以我们枚举s1的右端点,s1的长度乘以s2起始点为左边界的回文串的数量,累加就是答案。

所以先求s1,再求以每个点为左边界的回文串的数量

就是求每个后缀匹配第二个串的LCP(扩展kmp,或者hash+二分)二的话,后面部分用(Manacher+前缀和)就可以解决

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 const int maxn=1e6+50;
  4 char str[maxn*2],t[maxn*2],s[maxn*2];
  5 int dp[maxn*2],dpnext[maxn*2],dpret[maxn*2],suffix[maxn*2],last[maxn];
  6 void manacher(char tmp[],int length,int rad[])
  7 {
  8     for(int i=1,j=0,k;i<length;i+=k)
  9     {
 10         while(tmp[i-j-1]==tmp[i+j+1]) j++;
 11         rad[i]=j;
 12         for(k=1;k<=rad[i]&&rad[i-k]!=rad[i]-k;++k)
 13         {
 14             rad[i+k]=min(rad[i-k],rad[i]-k);
 15         }
 16         j=max(j-k,0);
 17     }
 18 }
 19 void ExtendedKMP(char *a,char *b,int M,int N,int *Next,int *ret)
 20 {
 21     int i,j,k;
 22     for(j=0;1+j<M&&a[j]==a[1+j];j++);
 23     Next[1]=j;
 24     k=1;
 25     for(i=2;i<M;i++)
 26     {
 27         int Len=k+Next[k],L=Next[i-k];
 28         if(L<Len-i)
 29         {
 30             Next[i]=L;
 31         }
 32         else
 33         {
 34             for(j=max(0,Len-i);i+j<M&&a[j]==a[i+j];j++);
 35             Next[i]=j;
 36             k=i;
 37         }
 38     }
 39     for(j=0;j<N&&j<M&&a[j]==b[j];j++);
 40     ret[0]=j;
 41     k=0;
 42     for(i=1;i<N;i++)
 43     {
 44         int Len=k+ret[k],L=Next[i-k];
 45         if(L<Len-i)
 46         {
 47             ret[i]=L;
 48         }
 49         else
 50         {
 51             for(j=max(0,Len-i);j<M&&i+j<N&&a[j]==b[i+j];j++);
 52             ret[i]=j;
 53             k=i;
 54         }
 55     }
 56 }
 57 int main()
 58 {
 59     int i,j,k,n,m,lens,lent;
 60     scanf(" %s",str);
 61     scanf(" %s",t);
 62     lens=strlen(str);
 63     lent=strlen(t);
 64     reverse(str,str+lens);
 65     s[0]='(';s[1]='#';
 66     for(i=0,j=2;i<lens;i++,j+=2)
 67     {
 68         s[j]=str[i];
 69         s[j+1]='#';
 70     }
 71     n=lens;
 72     lens=lens*2+3;
 73     s[lens-1]=')';
 74     manacher(s,lens,dp);
 75     ExtendedKMP(t,str,lent,n,dpnext,dpret);
 76     suffix[lens]=0;
 77     memset(last,0,sizeof(last));
 78     for(i=2;i<lens-2;i++)
 79     {
 80         long long maxdis;
 81         if(i%2==0)
 82         {
 83             maxdis=i/2+dp[i]/2-1;
 84             last[maxdis]++;
 85             last[i/2-2]--;
 86         }
 87         else
 88         {
 89             maxdis=i/2+dp[i]/2-1;
 90             if(dp[i]/2>0)
 91             {
 92                 last[maxdis]++;
 93                 last[i/2-1]-- ;
 94             }
 95         }    
 96     }
 97     suffix[n]=0;
 98     for(i=n-1;i>=0;i--)
 99         suffix[i]=suffix[i+1]+last[i];
100     long long ans=0;
101     for(i=0;i<n;i++)
102     {
103         long long len=dpret[i];
104         ans=ans+len*(suffix[i-1]);
105     }
106     printf("%lld\n",ans);
107 }

 

posted @ 2018-12-11 16:21  口香糖万岁  阅读(338)  评论(0编辑  收藏  举报