题意:给你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 ",ans); 107 }