bzoj 4503 两个串

来源:互联网 发布:网络电信诈骗防 编辑:程序博客网 时间:2024/06/06 18:03

4503: 两个串

Time Limit: 20 Sec  Memory Limit: 256 MB
Submit: 580  Solved: 259
[Submit][Status][Discuss]

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中只包含小写字母和“?”





【分析】

hzwer版本的#include<complex>太慢了...换了licone的struct complex 版本,跑起来挺快

FFT这个东西就是要跑脑洞...

这个题应该算是通配符匹配问题中的一类吧

把模式串翻转一下

令 c[j+m-1]=sigama{(a[j+i]-b[m-1-i)^2*b[m-1-i]}

展开以后有三只卷鸡,然后黑箱FFT = =

(还是要多加练习FFT啊...每次根本看不出来qwq)

(其实我现在才知道卷鸡可以带平方三次方什么的...黑箱果然还是不太好)



【代码】

#include<algorithm>#include<iostream>#include<cstring>#include<cstdio>#include<cmath>#define pi acos(-1)#define ll long long#define M(a) memset(a,0,sizeof a)#define fo(i,j,k) for(int i=j;i<=k;i++)using namespace std;const int mxn=400005;char s[mxn];int n,m,L,N,M;int R[mxn],ans[mxn];double pre[mxn],now[mxn];struct E{double r,f;  //real & fakeE (double u,double v) {r=u,f=v;}E () {}E operator + (E u) {return E(r+u.r,f+u.f);}E operator - (E u) {return E(r-u.r,f-u.f);}E operator * (E u) {return E(r*u.r-f*u.f,r*u.f+f*u.r);}E operator / (int v) {return E(r/v,f/v);}}a[mxn],b[mxn],c[mxn];inline void fft(E *a,int f){fo(i,0,n-1) if(i<R[i]) swap(a[i],a[R[i]]);for(int i=1;i<n;i<<=1){E wn(cos(pi/i),f*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=a[j+k],y=w*a[j+k+i];a[j+k]=x+y,a[j+k+i]=x-y;}}}if(f==-1) fo(i,0,n-1) a[i]=a[i]/n;}int main(){    scanf("%s",s);n=strlen(s);    fo(i,0,n-1) pre[i]=(double)s[i]-'a'+1;    scanf("%s",s);m=strlen(s);    fo(i,0,m-1) now[i]=s[m-i-1]=='?'?(double)0:(double)s[m-i-1]-'a'+1;    M=2*n;for(n=1;n<M;n<<=1) L++;M/=2;    fo(i,0,n-1) R[i]=(R[i>>1]>>1|((i&1)<<L-1));    //a^2*b    fo(i,0,M-1) a[i].r=pre[i]*pre[i],b[i].r=now[i];    fft(a,1),fft(b,1);    fo(i,0,n-1) c[i]=a[i]*b[i];    fo(i,0,n-1) a[i].r=a[i].f=b[i].r=b[i].f=0;    //2*a*b^2    fo(i,0,M-1) a[i].r=pre[i],b[i].r=now[i]*now[i];    fft(a,1),fft(b,1);    fo(i,0,n-1) c[i]=c[i]-a[i]*b[i]-a[i]*b[i];    fo(i,0,n-1) a[i].r=a[i].f=b[i].r=b[i].f=0;    //b^3    fo(i,0,M-1) a[i].r=(double)1,b[i].r=now[i]*now[i]*now[i];fft(a,1),fft(b,1);fo(i,0,n-1) c[i]=c[i]+a[i]*b[i];fft(c,-1);fo(i,m-1,M-1) if(fabs(c[i].r)<0.5) ans[++ans[0]]=i-m+1;fo(i,0,ans[0]) printf("%d\n",ans[i]);    return 0;}


1 0
原创粉丝点击