BZOJ 4503 两个串

    xiaoxiao2021-03-25  183

    Description

    兔子们在玩两个串的游戏。给定两个字符串S和T,兔子们想知道T在S中出现了几次, 分别在哪些位置出现。注意T中可能有“?”字符,这个字符可以匹配任何字符。

    Input

    两行两个字符串,分别代表S和T

    Output

    第一行一个正整数k,表示T在S中出现了几次 接下来k行正整数,分别代表T每次在S中出现的开始位置。按照从小到大的顺序输出,S下标从0开始。

    Sample Input

    bbabaababaaaaabaaaaaaaabaaabbbabaaabbabaabbbbabbbbbbabbaabbbababababbbbbbaaabaaabbbbbaabbbaabbbbabab a?aba?abba

    Sample Output

    0

    HINT

    S 长度不超过 10^5, T 长度不会超过 S。 S 中只包含小写字母, T中只包含小写字母和“?”

    Source

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    FFT~

    终于有一道自己写出来的FFT了……好感动……

    其实就是上一道的简化版,用sum{(a[i]-b[j])^2*b[j]}==0来记录两串相符,把式子拆开后发现是三次卷积,然后把b串翻转一下FFT就可以了~

    区分n,nn,mm!

    #include<cstdio> #include<cstring> #include<iostream> #include<cmath> using namespace std; #define pi acos(-1) #define N 100001 #define M 400010 int n,nn,mm,l,r[M],ans[M]; double a[N],b[N]; char s[N]; struct E{ double r,i; E (double u,double v) {r=u;i=v;} E () {} E operator + (E u) {return E(r+u.r,i+u.i);} E operator - (E u) {return E(r-u.r,i-u.i);} E operator * (E u) {return E(r*u.r-i*u.i,r*u.i+i*u.r);} }f1[M],f2[M],c[M]; E operator / (E u,int v) {return E(u.r/v,u.i/v);} void fft(E *u,int v) { for(int i=0;i<n;i++) if(i<r[i]) swap(u[i],u[r[i]]); for(int i=1;i<n;i<<=1) { E wn(cos(pi/i),v*sin(pi/i)); for(int j=0;j<n;j+=(i<<1)) { E w(1,0); for(int k=0;k<i;k++,w=w*wn) { E x=u[j+k],y=w*u[i+j+k]; u[j+k]=x+y;u[i+j+k]=x-y; } } } if(v==-1) for(int i=0;i<n;i++) u[i]=u[i]/n; } int main() { scanf("%s",s);nn=strlen(s); for(int i=0;i<nn;i++) a[i]=(double)s[i]-'a'+1; scanf("%s",s);mm=strlen(s); for(int i=0;i<mm;i++) b[i]=s[mm-i-1]=='?' ? (double)0:(double)s[mm-i-1]-'a'+1; for(n=1;n<2*nn;n<<=1) l++; for(int i=0;i<n;i++) r[i]=(r[i>>1]>>1)|((i&1)<<(l-1)); for(int i=0;i<nn;i++) f1[i].r=a[i]*a[i],f2[i].r=b[i]; fft(f1,1);fft(f2,1); for(int i=0;i<n;i++) c[i]=f1[i]*f2[i]; for(int i=0;i<n;i++) f1[i].r=f1[i].i=f2[i].r=f2[i].i=0; for(int i=0;i<nn;i++) f1[i].r=a[i],f2[i].r=b[i]*b[i]; fft(f1,1);fft(f2,1); for(int i=0;i<n;i++) c[i]=c[i]-f1[i]*f2[i]-f1[i]*f2[i]; for(int i=0;i<n;i++) f1[i].r=f1[i].i=f2[i].r=f2[i].i=0; for(int i=0;i<nn;i++) f1[i].r=(double)1,f2[i].r=b[i]*b[i]*b[i]; fft(f1,1);fft(f2,1); for(int i=0;i<n;i++) c[i]=c[i]+f1[i]*f2[i]; fft(c,-1); for(int i=mm-1;i<nn;i++) if(fabs(c[i].r)<0.5) ans[++ans[0]]=i-mm+1; for(int i=0;i<=ans[0];i++) printf("%d\n",ans[i]); return 0; }

    转载请注明原文地址: https://ju.6miu.com/read-782.html

    最新回复(0)