BZOJ 3160: 万径人踪灭
题解
算出所有的回文子序列减去连续的
先在中间插好*
用f[i]表示以i为对称中心的对称位置有多少对
位置i的贡献为2f[i]-1
然后用manacher算不合法的
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 using namespace std; 6 const int maxn=600009; 7 const double pi=acos(-1.0); 8 const int mm=1000000007; 9 10 int n; 11 char T[maxn]; 12 long long ans=0; 13 long long ft[maxn]; 14 15 struct Cpx{ 16 double x,y; 17 Cpx(){ 18 x=y=0.0; 19 } 20 Cpx(double xx,double yy){ 21 x=xx;y=yy; 22 } 23 }Pa[maxn]; 24 25 Cpx operator + (Cpx z1,Cpx z2){ 26 return Cpx(z1.x+z2.x,z1.y+z2.y); 27 } 28 Cpx operator - (Cpx z1,Cpx z2){ 29 return Cpx(z1.x-z2.x,z1.y-z2.y); 30 } 31 Cpx operator * (Cpx z1,Cpx z2){ 32 return Cpx(z1.x*z2.x-z1.y*z2.y,z1.x*z2.y+z2.x*z1.y); 33 } 34 35 int rev[maxn]={0}; 36 void FFT(Cpx *arr,int n,int f){ 37 int b=0; 38 for(int len=1;len<n;len<<=1)b++; 39 for(int i=0;i<n;++i)rev[i]=(rev[i>>1]>>1)|((i&1)<<(b-1)); 40 41 for(int i=0;i<n;++i)if(i<rev[i])swap(arr[i],arr[rev[i]]); 42 43 for(int k=1;k<n;k<<=1){ 44 int p=k+k; 45 Cpx wn=Cpx(cos(pi/k),f*sin(pi/k)); 46 for(int i=0;i<n;i+=p){ 47 Cpx w=Cpx(1.0,0.0); 48 for(int j=0;j<k;++j,w=w*wn){ 49 Cpx x=arr[i+j],y=w*arr[i+j+k]; 50 arr[i+j]=x+y; 51 arr[i+j+k]=x-y; 52 } 53 } 54 } 55 if(f==-1){ 56 for(int i=0;i<n;++i)arr[i].x=arr[i].x/(n*1.0); 57 } 58 } 59 60 61 char s[maxn]; 62 int p[maxn]={0}; 63 void Manacher(int n){ 64 int mxlen=0,mxpla=0; 65 for(int i=1;i<=n;++i){ 66 if(mxpla+mxlen>i){ 67 p[i]=min(mxpla+mxlen-i,p[mxpla*2-i]); 68 } 69 while(s[i-p[i]]==s[i+p[i]])++p[i]; 70 if(i+p[i]>mxpla+mxlen){ 71 mxpla=i;mxlen=p[i]; 72 } 73 } 74 } 75 76 int f[maxn]; 77 78 int main(){ 79 scanf("%s",T+1); 80 int len=strlen(T+1); 81 s[++n]='*'; 82 for(int i=1;i<=len;++i){ 83 s[++n]=T[i]; 84 s[++n]='*'; 85 } 86 s[++n]='#'; 87 88 89 for(len=1;len<=(n*2);len<<=1); 90 for(int i=0;i<len;++i){ 91 Pa[i].x=Pa[i].y=0.0; 92 if(s[i]=='a')Pa[i].x=1.0; 93 } 94 // for(int i=0;i<len;++i)cout<<Pa[i].x<<' '; 95 // cout<<endl; 96 FFT(Pa,len,1); 97 98 for(int i=0;i<len;++i)Pa[i]=Pa[i]*Pa[i]; 99 FFT(Pa,len,-1); 100 // for(int i=0;i<len;++i)printf("%.0f ",Pa[i].x); 101 // cout<<endl; 102 for(int i=1;i<=n;++i){ 103 int t=(int)(Pa[i*2].x+0.5); 104 f[i]+=(t+1)/2; 105 } 106 107 for(int i=0;i<len;++i){ 108 Pa[i].x=Pa[i].y=0.0; 109 if(s[i]=='b')Pa[i].x=1.0; 110 } 111 FFT(Pa,len,1); 112 for(int i=0;i<len;++i)Pa[i]=Pa[i]*Pa[i]; 113 FFT(Pa,len,-1); 114 for(int i=1;i<=n;++i){ 115 int t=(int)(Pa[i*2].x+0.5); 116 f[i]+=(t+1)/2; 117 } 118 119 Manacher(n); 120 121 // for(int i=1;i<=n;++i)cout<<p[i]<<' '; 122 // cout<<endl; 123 124 ft[0]=1; 125 for(int i=1;i<=n;++i)ft[i]=(ft[i-1]<<1)%mm; 126 for(int i=1;i<=n;++i){ 127 ans=(ans+ft[f[i]]-1+mm)%mm; 128 ans=(ans-p[i]/2+mm)%mm; 129 } 130 131 cout<<ans<<endl; 132 return 0; 133 }
致歉:笔者已经意识到这是一篇几乎没有价值的文章,给您的阅读带来不好的体验,并且干扰了您的搜索环境,非常抱歉!