0
点赞
收藏
分享

微信扫一扫

bzoj 4503 两个串


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 & 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;
}



举报

相关推荐

0 条评论