【bzoj4259】 残缺的字符串 FFT
又是一道FFT套路题
思路可以参考bzoj4503,题解
我们对串S和串T中出现的*处全部赋值为0。
反正最终的差异度式子大概就是
$C[i]=\sum_{j=0}^{|T|-1}S[i+j]T[j](S[i+j]-T[j])^2$
然后和上一题一样的展开方式,将T串reverse一下做FFT再统计下即可。
然后这题卡常,FFT的长度是100W,所以用NTT会被卡常(我就T了)
然后就没了
1 #include<bits/stdc++.h> 2 #define PI acos(-1) 3 #define zero(x) (fabs(x)<0.5) 4 #define M 1<<20 5 using namespace std; 6 struct cp{ 7 double r,i; 8 cp(){r=i=0;} cp(int x){r=x; i=0;} 9 cp(double rr,double ii){r=rr;i=ii;} 10 friend cp operator +(cp a,cp b){return cp(a.r+b.r,a.i+b.i);} 11 friend cp operator -(cp a,cp b){return cp(a.r-b.r,a.i-b.i);} 12 friend cp operator *(cp a,cp b){return cp(a.r*b.r-a.i*b.i,a.r*b.i+a.i*b.r);} 13 }; 14 15 cp a[M]={0},aa[M]={0},aaa[M]={0}; 16 cp b[M]={0},bb[M]={0},bbb[M]={0}; 17 int n; cp ans[M]={0}; 18 19 void change(cp a[],int n){ 20 for(int i=0,j=0;i<n-1;i++){ 21 if(i<j) swap(a[i],a[j]); 22 int k=n>>1; 23 while(j>=k) j-=k,k>>=1; 24 j+=k; 25 } 26 } 27 void FFT(cp a[],int n,int on){ 28 change(a,n); 29 for(int h=2;h<=n;h<<=1){ 30 cp wn=cp(cos(2*PI/h),on*sin(2*PI/h)); 31 for(int j=0;j<n;j+=h){ 32 cp w=cp(1,0); 33 for(int k=j;k<j+(h>>1);k++){ 34 cp u=a[k],t=w*a[k+(h>>1)]; 35 a[k]=u+t; 36 a[k+(h>>1)]=u-t; 37 w=w*wn; 38 } 39 } 40 } 41 if(on==-1) for(int i=0;i<n;i++) a[i].r/=n; 42 } 43 44 char s[M]={0},c[M]={0}; 45 int lens,lenc,len=1; 46 int main(){ 47 scanf("%d%d",&lens,&lenc); 48 scanf("%s%s",c,s); 49 lens=strlen(s); lenc=strlen(c); 50 while(len<lens+lenc) len<<=1; 51 reverse(c,c+lenc); 52 for(int i=0;i<lens;i++) a[i]=(s[i]=='*'?0:s[i]-'a'+1),aa[i]=a[i]*a[i],aaa[i]=aa[i]*a[i]; 53 for(int i=0;i<lenc;i++) b[i]=(c[i]=='*'?0:c[i]-'a'+1),bb[i]=b[i]*b[i],bbb[i]=bb[i]*b[i]; 54 FFT(a,len,1); FFT(aa,len,1); FFT(aaa,len,1); 55 FFT(b,len,1); FFT(bb,len,1); FFT(bbb,len,1); 56 for(int i=0;i<len;i++) ans[i]=aaa[i]*b[i]-2*aa[i]*bb[i]+a[i]*bbb[i]; 57 FFT(ans,len,-1); 58 int sum=0; 59 for(int i=lenc-1;i<lens;i++) 60 if(zero(ans[i].r)) sum++; 61 cout<<sum<<endl; 62 for(int i=lenc-1;i<lens;i++) 63 if(zero(ans[i].r)) printf("%d ",i-lenc+2); 64 }