洛谷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$说明匹配上了

扫描二维码关注公众号,回复: 3446899 查看本文章

然而……通配符怎么办……如果有一位有通配符,那么这一位代表的编码相减肯定是$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 }

猜你喜欢

转载自www.cnblogs.com/bztMinamoto/p/9748340.html
今日推荐