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 }

 

posted @ 2017-04-19 15:34  ws_ccd  阅读(327)  评论(0编辑  收藏  举报