bzoj 4503 两个串 fft
两个串
Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 1078 Solved: 434
[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中只包含小写字母和“?”
题解:判断两个串,第二个在第一个中出现次数,这类问题ac自动机,kmp
但是第二个串有通配符,这个应该怎么办,其实可以这样判,就是对于
这个就是个卷积的形式,对于通配符就是如果是的话就直接为0,就是再乘个数的问题吧,将第二个串反一下就是个卷积了。
1 #include<cstring> 2 #include<iostream> 3 #include<cstdio> 4 #include<algorithm> 5 #include<cmath> 6 7 #define ll long long 8 #define N 100007 9 #define pi acos(-1) 10 using namespace std; 11 inline int read() 12 { 13 int x=0,f=1;char ch=getchar(); 14 while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} 15 while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} 16 return x*f; 17 } 18 19 int n,m,res,num,L; 20 double hjq; 21 int c[N],d[N],rev[N]; 22 ll ans[N<<2]; 23 char ch[N]; 24 25 struct comp 26 { 27 double r,v; 28 comp(){} 29 comp(double a,double b){r=a,v=b;} 30 friend inline comp operator+(comp x,comp y){return comp(x.r+y.r,x.v+y.v);} 31 friend inline comp operator-(comp x,comp y){return comp(x.r-y.r,x.v-y.v);} 32 friend inline comp operator*(comp x,comp y){return comp(x.r*y.r-x.v*y.v,x.r*y.v+x.v*y.r);} 33 }a1[N<<2],b1[N<<2],a2[N<<2],b2[N<<2],fzy[N<<2]; 34 35 void FFT(comp *a,int flag) 36 { 37 for (int i=0;i<num;i++) 38 if (i<rev[i]) swap(a[i],a[rev[i]]); 39 for (int i=1;i<num;i<<=1) 40 { 41 comp wn=comp(cos(pi/i),flag*sin(pi/i)); 42 for (int j=0;j<num;j+=(i<<1)) 43 { 44 comp w=comp(1,0); 45 for (int k=0;k<i;k++,w=w*wn) 46 { 47 comp x=a[j+k],y=w*a[j+k+i]; 48 a[j+k]=x+y,a[j+k+i]=x-y; 49 } 50 } 51 } 52 if (flag==-1) for (int i=0;i<num;i++) a[i].r/=num; 53 } 54 int main() 55 { 56 scanf("%s",ch),n=strlen(ch); 57 for (int i=0;i<n;i++) c[i]=ch[i]-'a'+1; 58 scanf("%s",ch),m=strlen(ch); 59 for (int i=0;i<m;i++) d[i]=(ch[m-i-1]=='?')?0:ch[m-i-1]-'a'+1; 60 61 for (int i=0;i<n;i++) a1[i].r=1.0*c[i]*c[i]; 62 for (int i=0;i<m;i++) b1[i].r=1.0*d[i]; 63 for (int i=0;i<n;i++) a2[i].r=-2.0*c[i]; 64 for (int i=0;i<m;i++) b2[i].r=1.0*d[i]*d[i]; 65 for (int i=0;i<m;i++) hjq+=d[i]*d[i]*d[i]; 66 67 68 for (num=1;num<=n+m-1;num<<=1,L++);if (L) L--; 69 for (int i=0;i<num;i++) rev[i]=(rev[i>>1]>>1)|((i&1)<<L); 70 FFT(a1,1),FFT(b1,1),FFT(a2,1),FFT(b2,1); 71 for (int i=0;i<num;i++) fzy[i]=a1[i]*b1[i]+a2[i]*b2[i]; 72 FFT(fzy,-1); 73 for (int i=0;i<num;i++) ans[i]=(ll)(hjq+fzy[i].r+0.5); 74 for (int i=m-1;i<n;i++) if (!ans[i]) res++; 75 printf("%d\n",res); 76 for (int i=m-1;i<n;i++) 77 if (!ans[i]) printf("%d\n",i-m+1); 78 }