洛谷P4173 残缺的字符串(FFT)
话说为什么字符串会和卷积扯上关系呢……到底得脑洞大到什么程度才能想到这种东西啊……大佬太珂怕了……
因为通配符的关系,自动机已经废了
那么换种方式考虑,如果两个字符串每一位对应的编码都相等,那么这两个字符串相等
编码相等就代表$\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 }
深深地明白自己的弱小