首页 > 代码库 > bzoj 4259: 残缺的字符串

bzoj 4259: 残缺的字符串

  这题好神啊,居然是fft,表示一直在往数据结构上想。

  把‘*‘当成0,那么两个串可以匹配当且仅当$$\sum (a[i]-b[i])^2\times a[i]\times b[i]==0$$

  我们可以把平方拆开,然后就变成了几个乘积相加的形式,那就大力翻转一个串然后跑FFT。

  因为最开始MLE了所以复制粘贴了好多东西。

  

  1 #include<iostream>
  2 #include<cstring>
  3 #include<cstdio>
  4 #include<algorithm>
  5 #include<cmath>
  6 #define N 1200005
  7 #define M 300005
  8 #define pi acos(-1)
  9 #define E complex
 10 using namespace std;
 11 struct complex
 12 {
 13     double x,y;
 14     complex(double _x,double _y){x=_x;y=_y;}
 15     complex(){;}
 16     friend complex operator * (const complex &a,const complex &b)
 17     {
 18         complex c;c.x=a.x*b.x-a.y*b.y;c.y=a.x*b.y+a.y*b.x;return c;
 19     }
 20     friend complex operator / (complex a,double b)
 21     {
 22         return complex(a.x/b,a.y/b);
 23     }
 24     friend complex operator + (complex a,complex b)
 25     {
 26         return complex(a.x+b.x,a.y+b.y);
 27     }
 28     friend complex operator - (complex a,complex b)
 29     {
 30         return complex(a.x-b.x,a.y-b.y);
 31     }
 32 };
 33 int R[N];int n;
 34 void fft(E *a,int f)
 35 {
 36     for(int i=0;i<n;i++)if(i<R[i])swap(a[i],a[R[i]]);
 37     for(int i=1;i<n;i<<=1)
 38     {
 39         E wn(cos(pi/i),f*sin(pi/i));
 40         for(int j=0;j<n;j+=(i<<1))
 41         {
 42             E w(1,0);
 43             for(int k=0;k<i;k++,w=w*wn)
 44             {
 45                 E x=a[j+k],y=w*a[j+k+i];
 46                 a[j+k]=x+y;a[j+k+i]=x-y;
 47             }
 48         }
 49     }
 50     if(f==-1)for(int i=0;i<n;i++)a[i]=a[i]/n;
 51 }
 52 int nn,mm;
 53 char s1[M],s2[M],s3[M];
 54 E a1[N],b1[N],c1[N];
 55 int ans[N];
 56 int st[M],top;
 57 int main()
 58 {
 59     scanf("%d%d",&nn,&mm);
 60     scanf("%s",s3);scanf("%s",s2);
 61     int l=0;
 62     for(n=1;n<2*mm;n<<=1)l++;
 63     for(int i=0;i<n;i++)R[i]=(R[i>>1]>>1)|((i&1)<<(l-1));
 64     for(int i=0;i<nn;i++)s1[i]=s3[nn-i-1];
 65     for(int i=0;i<mm;i++)
 66     {
 67         int tmp=s2[i]-a+1;double p=tmp+0.0;
 68         if(s2[i]==*)p=0;
 69         b1[i].x=p;
 70     }
 71     for(int i=0;i<nn;i++)
 72     {
 73         int tmp=s1[i]-a+1;double p=tmp+0.0;
 74         if(s1[i]==*)p=0;
 75         a1[i].x=p*p*p;
 76     }
 77     fft(a1,1);fft(b1,1);
 78     for(int i=0;i<n;i++)c1[i]=a1[i]*b1[i];
 79     for(int i=0;i<n;i++)a1[i].x=a1[i].y=b1[i].x=b1[i].y=0;
 80     
 81     for(int i=0;i<mm;i++)
 82     {
 83         int tmp=s2[i]-a+1;double p=tmp+0.0;
 84         if(s2[i]==*)p=0;
 85         b1[i].x=p*p;
 86     }
 87     for(int i=0;i<nn;i++)
 88     {
 89         int tmp=s1[i]-a+1;double p=tmp+0.0;
 90         if(s1[i]==*)p=0;
 91         a1[i].x=p*p;
 92     }
 93     fft(a1,1);fft(b1,1);
 94     for(int i=0;i<n;i++)c1[i]=c1[i]-(a1[i]*b1[i]),c1[i]=c1[i]-(a1[i]*b1[i]);
 95     for(int i=0;i<n;i++)a1[i].x=a1[i].y=b1[i].x=b1[i].y=0;
 96 
 97     for(int i=0;i<mm;i++)
 98     {
 99         int tmp=s2[i]-a+1;double p=tmp+0.0;
100         if(s2[i]==*)p=0;
101         b1[i].x=p*p*p;
102     }
103     for(int i=0;i<nn;i++)
104     {
105         int tmp=s1[i]-a+1;double p=tmp+0.0;
106         if(s1[i]==*)p=0;
107         a1[i].x=p;
108     }
109     fft(a1,1);fft(b1,1);
110     for(int i=0;i<n;i++)c1[i]=c1[i]+(a1[i]*b1[i]);
111     
112     fft(c1,-1);
113 
114     for(int i=nn-1;i<mm;i++)
115     {
116         if(fabs(c1[i].x)<0.5)
117         {
118             st[++top]=i-nn+2;
119         }
120     }
121     printf("%d\n",top);
122     for(int i=1;i<=top;i++)
123     {
124         if(i!=top)printf("%d ",st[i]);
125         else printf("%d\n",st[i]);
126     }
127     return 0;
128 }

 

bzoj 4259: 残缺的字符串