BZOJ3160: 万径人踪灭
设a[i]=bool(s[i]=='a'),b[i]=bool(s[i]=='b'),考虑a和a、b和b的卷积,由于卷积是对称的,就可以统计出不连续回文子串个数了。可能说得比较简略。再用manacher算出连续回文子串个数并减去。
#include<bits/stdc++.h> using namespace std; const int p=1e9+7; const int N=1<<18; typedef double flo; const flo pi=acos((flo)-1); struct vec{flo x,y;}; vec operator+(vec a,vec b){return{a.x+b.x,a.y+b.y};} vec operator-(vec a,vec b){return{a.x-b.x,a.y-b.y};} vec operator*(vec a,vec b){return{a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x};} void fft(vec*c,int n,int d){ static int f[N]; f[1]=n>>1; for(int i=2;i<n;++i){ f[i]=f[i>>1]>>1|f[i&1]; if(i>f[i]) swap(c[i],c[f[i]]); } for(int i=1;i<n;i*=2){ vec w={cos(pi/i*d),sin(pi/i*d)}; for(int j=0;j<n;j+=i*2){ vec s={1}; for(int k=j;k<j+i;++k){ vec v=s*c[k+i]; c[k+i]=c[k]-v,c[k]=c[k]+v,s=s*w; } } } if(!~d) for(int i=0;i<n;++i) c[i].x/=n; } char z[N]; vec a[N],b[N]; int c[N],f[N]; int main(){ scanf("%s",z); int n=strlen(z); int m=4<<__lg(n); for(int i=0;i<n;++i){ a[i].x=98-z[i]; b[i].x=z[i]-97; } fft(a,m,1); fft(b,m,1); for(int i=0;i<m;++i) a[i]=a[i]*a[i]+b[i]*b[i]; fft(a,m,-1); for(int i=1;i<=n;++i) c[i]=(c[i-1]*2+1)%p; int s=0; for(int i=0;i<m;++i){ int j=a[i].x+.5; (s+=c[(j+1)/2])%=p; } for(int i=n-1;~i;--i){ z[i*2+2]=z[i]; z[i*2+3]='#'; } z[1]='#'; z[0]='^'; for(int i=1,j=0;z[i];++i){ int k=j+f[j]; f[i]=i<k?min(f[j*2-i],k-i):1; if(i+f[i]>=k){ j=i; while(z[i-f[i]]==z[i+f[i]]) ++f[i]; } (s+=p-f[i]/2)%=p; } printf("%d\n",s); }