1. 程式人生 > >洛谷P4173 殘缺的字符串(FFT)

洛谷P4173 殘缺的字符串(FFT)

htm 字符 說明 腦洞 problem tmp d+ hellip sin

傳送門

話說為什麽字符串會和卷積扯上關系呢……到底得腦洞大到什麽程度才能想到這種東西啊……大佬太珂怕了……

因為通配符的關系,自動機已經廢了

那麽換種方式考慮,如果兩個字符串每一位對應的編碼都相等,那麽這兩個字符串相等

編碼相等就代表$\sum_{i=1}^na[i]-b[i]=0$

然而這是不對的,有可能前面少一點,後面多一點,最好加起來還是$0$

那就平方一下$\sum_{i=1}^n(a[i]-b[i]=0)^2=0$,那就大丈夫了

於是我們得到了比一位一位匹配更麻煩的方法

看到平方……把它展開一下試試……結果……$\sum_{i=1}^na[i]^2+b[i]^2-2a[i]b[i]$

我們考慮把$b$給倒過來……這就是三個卷積啊!直接用FFT啊!加起來之後如果為$0$說明匹配上了

然而……通配符怎麽辦……如果有一位有通配符,那麽這一位代表的編碼相減肯定是$0$了

那麽再改一下$\sum_{i=1}^na[i]*b[i]*(a[i]-b[i])=0$,如果一個位置是通配符,就把$a[i]/b[i]$設為$0$

然後就沒有問題了……求一下卷積……如果第$i$位為$0$那麽它就是一個能匹配上的字符串的結尾

 1 //minamoto
 2 #include<iostream>
 3
#include<cstdio> 4 #include<cmath> 5 using namespace std; 6 const int N=1100005;const double Pi=acos(-1.0); 7 struct complex{ 8 double x,y; 9 complex(double xx=0,double yy=0){x=xx,y=yy;} 10 complex operator +(complex b){return complex(x+b.x,y+b.y);} 11 complex operator
-(complex b){return complex(x-b.x,y-b.y);} 12 complex operator *(complex b){return complex(x*b.x-y*b.y,x*b.y+y*b.x);} 13 }A[N],B[N],C[N]; 14 int n,m,l,r[N],limit=1;double a[N],b[N]; 15 void FFT(complex *A,int type){ 16 for(int i=0;i<limit;++i) 17 if(i<r[i]) swap(A[i],A[r[i]]); 18 for(int mid=1;mid<limit;mid<<=1){ 19 complex Wn(cos(Pi/mid),type*sin(Pi/mid)); 20 for(int R=mid<<1,j=0;j<limit;j+=R){ 21 complex w(1,0); 22 for(int k=0;k<mid;++k,w=w*Wn){ 23 complex x=A[j+k],y=w*A[j+mid+k]; 24 A[j+k]=x+y,A[j+mid+k]=x-y; 25 } 26 } 27 } 28 if(type==-1) 29 for(int i=0;i<limit;++i) A[i]=(int)(A[i].x/limit+0.5); 30 } 31 char s1[300005],s2[300005];int l1,l2,ans[N],res=0; 32 int main(){ 33 // freopen("testdata.in","r",stdin); 34 scanf("%d%d",&l2,&l1); 35 scanf("%s%s",s2,s1); 36 m=l1+l2; 37 while(limit<=m) limit<<=1,++l; 38 for(int i=0;i<limit;++i) 39 r[i]=(r[i>>1]>>1)|((i&1)<<(l-1)); 40 for(int i=0;i<l1;++i) 41 a[i]=s1[i]==*?0:s1[i]-a+1; 42 for(int i=0;i<l2;++i) 43 b[l2-i-1]=s2[i]==*?0:s2[i]-a+1; 44 for(int i=0;i<l1;++i) A[i].x=a[i]*a[i]*a[i]; 45 for(int i=0;i<l2;++i) B[i].x=b[i]; 46 FFT(A,1),FFT(B,1); 47 for(int i=0;i<limit;++i) C[i]=A[i]*B[i];//a^3*b 48 for(int i=0;i<limit;++i) A[i].x=a[i]*a[i],A[i].y=0; 49 for(int i=0;i<limit;++i) B[i].x=b[i]*b[i],B[i].y=0; 50 FFT(A,1),FFT(B,1); 51 complex tmp(2,0); 52 for(int i=0;i<limit;++i) C[i]=C[i]-A[i]*B[i]*tmp;//-2ab*a*b 53 for(int i=0;i<limit;++i) A[i].x=a[i],A[i].y=0; 54 for(int i=0;i<limit;++i) B[i].x=b[i]*b[i]*b[i],B[i].y=0; 55 FFT(A,1),FFT(B,1); 56 for(int i=0;i<limit;++i) C[i]=C[i]+A[i]*B[i];//b^3*a 57 FFT(C,-1); 58 for(int i=l2-1;i<l1;++i) 59 if(C[i].x==0.0) ans[++res]=i-l2+2; 60 printf("%d\n",res); 61 for(int i=1;i<=res;++i) printf("%d ",ans[i]); 62 return 0; 63 }

洛谷P4173 殘缺的字符串(FFT)