bzoj 4259: 残缺的字符串
神啊,FFT真是无所不能。
可以这么想吧:
我们高(处)中(小学)老师教过我们判定2个东西是不是相等的方法,一个是做差等于0,一个是相除等于1,这个题就是用的做差等于0
所以现在对于每一位,做差即(ai-bi)而且现在有一些可以随意匹配,那就意味着这一位就直接是0,所以随后我们就是求一段和全为0的东西,
也就是 ∑(ai-bi)*ai*bi==0这个东西我们发现还是怪怪的,所以把一个串翻转,变成 ∑(aj-bi)*aj*bi==0(i+j是常数),哈!!233这不就是卷积嘛!
直接FFT就好,然后判段某一位是不是0就行了
1 #include <cstdio> 2 #include <iostream> 3 #include <cmath> 4 #include <cstring> 5 #define pi acos(-1) 6 using namespace std; 7 8 const int maxn=600005; 9 10 struct complex 11 { 12 double r,i; 13 complex (double a=0, double b=0) {r=a; i=b;} 14 complex operator + (const complex a) {return complex(r+a.r,i+a.i);} 15 complex operator - (const complex a) {return complex(r-a.r,i-a.i);} 16 complex operator * (const complex a) {return complex(r*a.r-i*a.i,r*a.i+i*a.r);} 17 }A[maxn<<1],B[maxn<<1],ans[maxn<<1]; 18 19 int N,n,m,cnt,Ans[maxn],a[maxn],b[maxn],rev[maxn]; 20 char s[maxn],t[maxn]; 21 22 void FFT(complex *a, int f) 23 { 24 for (int i=0; i<N; i++) if (i<rev[i]) swap(a[i],a[rev[i]]); 25 for (int h=2; h<=N; h<<=1) 26 { 27 complex wn(cos(2*pi*f/h),sin(2*pi*f/h)); 28 for (int i=0; i<N; i+=h) 29 { 30 complex w(1,0); 31 for (int j=0; j<(h>>1); j++,w=w*wn) 32 { 33 complex x=a[i+j],y=w*a[i+j+(h>>1)]; 34 a[i+j]=x+y; 35 a[i+j+(h>>1)]=x-y; 36 } 37 } 38 } 39 if (f==-1) for (int i=0; i<N; i++) a[i].r/=(double)N; 40 } 41 42 int main(int argc, char const *argv[]) 43 { 44 scanf("%d%d",&m,&n); 45 scanf("%s",s); scanf("%s",t); 46 for (int i=0; i<m; i++) a[i]=(s[m-i-1]=='*')?0:s[m-i-1]-'a'+1; 47 for (int i=0; i<n; i++) b[i]=(t[i]=='*')?0:t[i]-'a'+1; 48 int L=0; 49 for (N=1; N<(n+m); N<<=1) L++; 50 for (int i=0; i<N; i++) rev[i]=(rev[i>>1]>>1)|((i&1)<<(L-1)); 51 52 for (int i=0; i<m; i++) A[i]=a[i]*a[i]*a[i]; 53 for (int i=0; i<n; i++) B[i]=b[i]; 54 FFT(A,1); FFT(B,1); 55 for (int i=0; i<N; i++) ans[i]=A[i]*B[i]; 56 57 memset(A,0,sizeof(A)); memset(B,0,sizeof(B)); 58 for (int i=0; i<m; i++) A[i]=a[i]; 59 for (int i=0; i<n; i++) B[i]=b[i]*b[i]*b[i]; 60 FFT(A,1); FFT(B,1); 61 for (int i=0; i<N; i++) ans[i]=ans[i]+A[i]*B[i]; 62 63 memset(A,0,sizeof(A)); memset(B,0,sizeof(B)); 64 for (int i=0; i<m; i++) A[i]=2*a[i]*a[i]; 65 for (int i=0; i<n; i++) B[i]=b[i]*b[i]; 66 FFT(A,1); FFT(B,1); 67 for (int i=0; i<N; i++) ans[i]=ans[i]-A[i]*B[i]; 68 69 FFT(ans,-1); 70 for (int i=m-1; i<n; i++) if (ans[i].r<0.1 && ans[i].r>-0.1) Ans[++cnt]=i-m+2; 71 printf("%d\n",cnt); 72 for (int i=1; i<=cnt; i++) printf("%d ",Ans[i]); 73 return 0; 74 }