bzoj 4259 4259: 殘缺的字串【FFT】
阿新 • • 發佈:2018-11-29
和bzoj 4503 https://www.cnblogs.com/lokiii/p/10032311.html 差不多,就是再乘上一個原串字元
有點卡常,先在點值下算最後一起IDFT
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> using namespace std; const int N=1100005; int n,m,bt,lm,re[N],tot; long long x[N],y[N]; double sm; char s[N],t[N]; struct cd { double a,b; cd(double A=0,double B=0) { a=A,b=B; } cd operator + (const cd &x) const { return cd(a+x.a,b+x.b); } cd operator - (const cd &x) const { return cd(a-x.a,b-x.b); } cd operator * (const cd &x) const { return cd(a*x.a-b*x.b,a*x.b+b*x.a); } }a[N],b[N],c[N]; void dft(cd a[],int f) { for(int i=0;i<lm;i++) if(i<re[i]) swap(a[i],a[re[i]]); for(int i=1;i<lm;i<<=1) { cd wi=cd(cos(M_PI/i),f*sin(M_PI/i)); for(int k=0;k<lm;k+=(i<<1)) { cd w=cd(1,0),x,y; for(int j=0;j<i;j++) { x=a[j+k],y=w*a[i+j+k]; a[j+k]=x+y,a[i+j+k]=x-y; w=w*wi; } } } if(f==-1) for(int i=0;i<lm;i++) a[i].a/=lm; } int main() { scanf("%d%d%s%s",&n,&m,t,s); for(int i=0,j=n-1;i<j;i++,j--) swap(t[i],t[j]); for(int i=0;i<n;i++) x[i]=(t[i]=='*')?0:t[i]-'a'+1,a[i].a=x[i]*x[i]*x[i]; for(int i=0;i<m;i++) y[i]=(s[i]=='*')?0:s[i]-'a'+1,b[i].a=y[i]; for(bt=0;(1<<bt)<=n+m;bt++); lm=1<<bt; for(int i=0;i<lm;i++) re[i]=(re[i>>1]>>1)|((i&1)<<(bt-1)); dft(a,1),dft(b,1); for(int i=0;i<lm;i++) c[i]=c[i]+a[i]*b[i]; for(int i=0;i<lm;i++) a[i]=cd(x[i],0),b[i]=cd(y[i]*y[i]*y[i],0); dft(a,1),dft(b,1); for(int i=0;i<lm;i++) c[i]=c[i]+a[i]*b[i]; for(int i=0;i<lm;i++) a[i]=cd(x[i]*x[i],0),b[i]=cd(y[i]*y[i],0); dft(a,1),dft(b,1); for(int i=0;i<lm;i++) c[i]=c[i]-a[i]*b[i]*cd(2,0); dft(c,-1); for(int i=n-1;i<m;i++) if((int)(c[i].a+0.5)==0) tot++; printf("%d\n",tot); for(int i=n-1;i<m;i++) if((int)(c[i].a+0.5)==0) printf("%d ",i-n+2); return 0; }