bzoj 4259 残缺的字符串 FFT

残缺的字符串

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 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

Sample Output

2
1 5

HINT

 

Source

[Submit][Status][Discuss]


HOME Back


题解:其实和两个串差不多,就是第一个有了通配符,第二个有了通配符。

   然后第二个翻转卷积就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\n",res);
74     for (int i=m-1;i<n;i++)
75         if (!(ll)(fzy[i].r+0.5)) printf("%d ",i-m+2);
76 }

 

 

posted @ 2018-03-31 14:16  Kaiser-  阅读(87)  评论(0编辑  收藏  举报