给定模板串 A 和母串 B ,长度分别为 m 和 n ,你需要统计模板串在母串中所有出现的位置。
字符集都是小写拉丁字母,而且存在通配符 ∗ 能够匹配任意字符。
1≤m,n≤3×105
考虑将 A 串倒置,然后令
为什么我的DFT跑起来的时间是别人的两倍。。。
于是BZOJ上T成狗。。。
有没有大神来指明一下哪里常数大了???
#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cctype>
#include <cmath>
#define sqr(x) (x*x)
#define cube(x) (x*x*x)
using namespace std;
typedef double db;
int buf[30];
void write(int x)
{
if (x<0) putchar('-'),x=-x;
for (;x;x/=10) buf[++buf[0]]=x%10;
if (!buf[0]) buf[++buf[0]]=0;
for (;buf[0];putchar('0'+buf[buf[0]--]));
}
const db pi=acos(-1);
const int N=524300;
struct Z
{
db x,y;
inline Z(){}
inline Z(db x_,db y_):x(x_),y(y_){};
inline Z operator+(Z const p){return Z(x+p.x,y+p.y);}
inline Z operator-(Z const p){return Z(x-p.x,y-p.y);}
inline Z operator*(Z const p){return Z(x*p.x-y*p.y,x*p.y+y*p.x);}
inline Z operator/(db const k){return Z(x/k,y/k);}
}A[N],B[N],C[N],t[N],omega[N];
db S_[N],T_[N],res[N];
int trs[N],mat[N];
char S[N],T[N];
int n,m,L,cnt;
void DFT(Z *a,int len,int sig)
{
for (int i=0;i<len;++i) t[trs[i]]=a[i];
Z w;
for (int l=2,half,p;l<=len;l<<=1)
{
half=l>>1,p=len/l;
for (int i=0;i<half;++i)
{
w=omega[sig>0?p*i:len-p*i];
for (int j=i;j<len;j+=l)
{
Z u=t[j],v=w*t[j+half];
t[j]=u+v,t[j+half]=u-v;
}
}
}
for (int i=0;i<len;++i) a[i]=t[i];
}
void pre()
{
for (L=1;L<n||L<m;L<<=1);
for (int i=0;i<L;++i)
{
int ret=0;
for (int j=1,x=i;j<L;j<<=1,x>>=1) ret=ret<<1|(x&1);
trs[i]=ret;
}
for (int i=0;i<=L;++i) omega[i]=Z(cos(2.*pi*i/L),sin(2.*pi*i/L));
}
void calc()
{
for (int i=0;i<n;++i) S_[i]=S[i]=='*'?0:S[i]-'a'+1;
for (int i=0;i<m;++i) T_[i]=T[i]=='*'?0:T[i]-'a'+1;
for (int i=0;i<L;++i) A[i]=Z(cube(S_[i]),0);
for (int i=0;i<L;++i) B[i]=Z(T_[i],0);
DFT(A,L,1),DFT(B,L,1);
for (int i=0;i<L;++i) C[i]=A[i]*B[i];
DFT(C,L,-1);
for (int i=0;i<n;++i) C[i]=C[i]/L;
for (int i=0;i<n;++i) res[i]=round(C[i].x);
for (int i=0;i<L;++i) A[i]=Z(sqr(S_[i]),0);
for (int i=0;i<L;++i) B[i]=Z(sqr(T_[i]),0);
DFT(A,L,1),DFT(B,L,1);
for (int i=0;i<L;++i) C[i]=A[i]*B[i];
DFT(C,L,-1);
for (int i=0;i<n;++i) C[i]=C[i]/L;
for (int i=0;i<n;++i) res[i]-=2.*round(C[i].x);
for (int i=0;i<L;++i) A[i]=Z(S_[i],0);
for (int i=0;i<L;++i) B[i]=Z(cube(T_[i]),0);
DFT(A,L,1),DFT(B,L,1);
for (int i=0;i<L;++i) C[i]=A[i]*B[i];
DFT(C,L,-1);
for (int i=0;i<n;++i) C[i]=C[i]/L;
for (int i=0;i<n;++i) res[i]+=round(C[i].x);
}
int main()
{
freopen("string.in","r",stdin),freopen("string.out","w",stdout);
scanf("%d%d",&m,&n);
scanf("%s",T),scanf("%s",S),reverse(T,T+m),pre();
calc();
for (int i=m-1;i<n;++i)
if (fabs(res[i])<=1e-8) mat[++cnt]=i+2-m;
write(cnt),putchar('\n');
for (int i=1;i<=cnt;++i) write(mat[i]),putchar(i<cnt?' ':'\n');
fclose(stdin),fclose(stdout);
return 0;
}