4503: 两个串
Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 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
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 & fake
E (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;
}