版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sizeof_you/article/details/84555790
先不管
,考虑两个串的对应位置,如果
在
的
处出现则一定满足
这个拆开然后翻转
就是卷积的形式
再考虑
,发现只要把
的值赋为
,然后再在这个式子外乘上
就好了:
拆开以后用两次
,注意两次的变量要不一样(因为清空时候莫名其妙出了问题,改成不同的变量就对了)
代码如下:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define maxn 400005
using namespace std;
char s[maxn],t[maxn];
int lens,lent,limit=1,l,rev[maxn],cnt;
double f[maxn],sum;
const double Pi=acos(-1.0),eps=1e-2;
struct complex{
double x,y;
complex(double xx=0,double yy=0){x=xx,y=yy;}
}a[maxn],b[maxn],c[maxn],d[maxn];
complex operator +(complex a,complex b){return complex(a.x+b.x,a.y+b.y);}
complex operator -(complex a,complex b){return complex(a.x-b.x,a.y-b.y);}
complex operator *(complex a,complex b){return complex(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);}
inline void FFT(complex *F,int type){
for(int i=0;i<limit;i++)
if(i<rev[i]) swap(F[i],F[rev[i]]);
for(int mid=1;mid<limit;mid<<=1){
complex Wn(cos(Pi/mid),1.0*type*sin(Pi/mid));
for(int r=mid<<1,j=0;j<limit;j+=r){
complex w(1,0);
for(int k=0;k<mid;k++,w=w*Wn){
complex x=F[j+k],y=w*F[j+mid+k];
F[j+k]=x+y,F[j+mid+k]=x-y;
}
}
}
}
int main(){
scanf("%s%s",s,t); lens=strlen(s); lent=strlen(t);
for(int i=0;i<lens;i++) a[i].x=s[i]-'a'+1,a[i].x=a[i].x*a[i].x;
for(int i=0;i<lent;i++)
if(t[i]=='?') b[lent-i-1].x=0;
else b[lent-i-1].x=t[i]-'a'+1;
for(int i=0;i<lent;i++) sum+=b[i].x*b[i].x*b[i].x;
while(limit<lens+lent) limit<<=1,++l;
for(int i=0;i<limit;i++)
rev[i]=(rev[i>>1]>>1)|((i&1)<<(l-1));
FFT(a,1); FFT(b,1);
for(int i=0;i<=limit;i++) a[i]=a[i]*b[i];
FFT(a,-1);
for(int i=lent-1;i<lens;i++)
f[i-lent+1]+=((a[i].x/limit)+0.5);
for(int i=0;i<lens;i++) c[i].x=s[i]-'a'+1,c[i].x=c[i].x*2.0;
for(int i=0;i<lent;i++)
if(t[lent-i-1]=='?') d[i].x=0;
else d[i].x=t[lent-i-1]-'a'+1,d[i].x=d[i].x*d[i].x;
FFT(c,1); FFT(d,1);
for(int i=0;i<=limit;i++) c[i]=c[i]*d[i];
FFT(c,-1);
for(int i=lent-1;i<lens;i++) {
f[i-lent+1]-=(c[i].x/limit+0.5);
f[i-lent+1]+=sum;
if(f[i-lent+1]<=eps && f[i-lent+1]>=-eps) cnt++;
}
printf("%d\n",cnt);
for(int i=lent-1;i<lens;i++)
if(f[i-lent+1]<=eps && f[i-lent+1]>=-eps) printf("%d\n",i-lent+1);
return 0;
}