残缺的字符串
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1327 Solved: 300
[Submit][Status][Discuss]
Description
很久很久以前,在你刚刚学习字符串匹配的时候,有两个仅包含小写字母的字符串A和B,其中A串长度为m,B串长度为n。可当你现在再次碰到这两个串时,这两个串已经老化了,每个串都有不同程度的残缺。
你想对这两个串重新进行匹配,其中A为模板串,那么现在问题来了,请回答,对于B的每一个位置i,从这个位置开始连续m个字符形成的子串是否可能与A串完全匹配?
Input
第一行包含两个正整数m,n(1<=m<=n<=300000),分别表示A串和B串的长度。
第二行为一个长度为m的字符串A。
第三行为一个长度为n的字符串B。
两个串均仅由小写字母和*号组成,其中*号表示相应位置已经残缺。
Output
第一行包含一个整数k,表示B串中可以完全匹配A串的位置个数。
若k>0,则第二行输出k个正整数,从小到大依次输出每个可以匹配的开头位置(下标从1开始)。
Sample Input
3 7
a*b
aebr*ob
a*b
aebr*ob
Sample Output
2
1 5
1 5
HINT
Source
题解:其实和两个串差不多,就是第一个有了通配符,第二个有了通配符。
然后第二个翻转卷积就ok了。
1 #include<cstring> 2 #include<iostream> 3 #include<cstdio> 4 #include<algorithm> 5 #include<cmath> 6 7 #define ll long long 8 #define N 1<<20 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,hjq,res,num,L; 20 int c[N],d[N],rev[N]; 21 char ch[N]; 22 23 struct comp 24 { 25 double r,v; 26 comp(){r=v=0.0;} 27 comp(double a,double b){r=a,v=b;} 28 friend inline comp operator+(comp x,comp y){return comp(x.r+y.r,x.v+y.v);} 29 friend inline comp operator-(comp x,comp y){return comp(x.r-y.r,x.v-y.v);} 30 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);} 31 }a1[N],b1[N],a2[N],b2[N],a3[N],b3[N],fzy[N]; 32 33 void FFT(comp *a,int flag) 34 { 35 for (int i=0;i<num;i++) 36 if (i<rev[i]) swap(a[i],a[rev[i]]); 37 for (int i=1;i<num;i<<=1) 38 { 39 comp wn=comp(cos(pi/i),flag*sin(pi/i)); 40 for (int j=0;j<num;j+=(i<<1)) 41 { 42 comp w=comp(1,0); 43 for (int k=0;k<i;k++,w=w*wn) 44 { 45 comp x=a[j+k],y=w*a[j+k+i]; 46 a[j+k]=x+y,a[j+k+i]=x-y; 47 } 48 } 49 } 50 if (flag==-1) for (int i=0;i<num;i++) a[i].r/=num; 51 } 52 int main() 53 { 54 m=read(),n=read(); 55 scanf("%s",ch);for (int i=0;i<m;i++) d[i]=(ch[m-i-1]=='*')?0:ch[m-i-1]-'a'+1; 56 scanf("%s",ch);for (int i=0;i<n;i++) c[i]=(ch[i]=='*')?0:ch[i]-'a'+1; 57 58 for (num=1;num<=n+m-1;num<<=1,L++);if (L) L--; 59 for (int i=0;i<num;i++) rev[i]=(rev[i>>1]>>1)|((i&1)<<L); 60 61 for (int i=0;i<n;i++) a1[i].r=c[i]*c[i]*c[i]; 62 for (int i=0;i<m;i++) b1[i].r=d[i]; 63 for (int i=0;i<n;i++) a2[i].r=-2*c[i]*c[i]; 64 for (int i=0;i<m;i++) b2[i].r=d[i]*d[i]; 65 for (int i=0;i<n;i++) a3[i].r=c[i]; 66 for (int i=0;i<m;i++) b3[i].r=d[i]*d[i]*d[i]; 67 68 FFT(a1,1),FFT(b1,1),FFT(a2,1),FFT(b2,1),FFT(a3,1),FFT(b3,1); 69 for (int i=0;i<num;i++) fzy[i]=a1[i]*b1[i]+a2[i]*b2[i]+a3[i]*b3[i]; 70 FFT(fzy,-1); 71 72 for (int i=m-1;i<n;i++) if (!(ll)(fzy[i].r+0.5)) res++; 73 printf("%d ",res); 74 for (int i=m-1;i<n;i++) 75 if (!(ll)(fzy[i].r+0.5)) printf("%d ",i-m+2); 76 }