# 【洛谷4173】残缺的字符串（重拾FFT）

### $FFT$与字符串匹配

$FFT$与字符串匹配，看似没有任何联系，实际上却大有用处。

### 推式子

$\sum_{k=0}^nA_kB_{i+k}(A_k-B_{i+k})^2$

$\sum_{k=0}^n(A_k^3B_{i+k}-2A_k^2B_{i+k}^2+A_kB_{i+k}^3)$

$\sum_{k=0}^n(T_{n-k}^3B_{i+k}-2T_{n-k}^2B_{i+k}^2+T_{n-k}B_{i+k}^3)$

$\sum_{x+y=n+i}(T_{x}^3B_{y}-2T_{x}^2B_{y}^2+T_{x}B_{y}^3)$

### 代码

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 300000
#define LL long long
#define DB double
using namespace std;
int n,m,a[4*N+5],b[4*N+5];char s[N+5];
template<int SZ> class Poly
{
private:
int P,L,R[4*N+5];DB Pi;
struct node
{
DB x,y;I node(Con DB& a=0,Con DB& b=0):x(a),y(b){}
I node operator + (Con node& o) Con {return node(x+o.x,y+o.y);}
I node operator - (Con node& o) Con {return node(x-o.x,y-o.y);}
I node operator * (Con node& o) Con {return node(x*o.x-y*o.y,x*o.y+y*o.x);}
}A[4*N+5],A2[4*N+5],A3[4*N+5],B[4*N+5],B2[4*N+5],B3[4*N+5];
I void T(node *s,CI op)
{
RI i,j,k;node U,S,x,y;for(i=0;i^P;++i) i<R[i]&&(U=s[i],s[i]=s[R[i]],s[R[i]]=U,0);
for(i=1;i^P;i<<=1) for(U=node(cos(Pi/i),op*sin(Pi/i)),j=0;j^P;j+=i<<1)
for(S=node(1,0),k=0;k^i;++k,S=S*U) s[j+k]=(x=s[j+k])+(y=S*s[i+j+k]),s[i+j+k]=x-y;
}
public:
I Poly() {Pi=acos(-1);}
Tp I void FFT(CI n,CI m,Ty *a,Ty *b)
{
RI i;P=1,L=0;W(P<=n+m) P<<=1,++L;for(i=0;i^P;++i) R[i]=(R[i>>1]>>1)|((i&1)<<L-1);
for(i=0;i<=n;++i) A[i]=a[i],A2[i]=A[i]*A[i],A3[i]=A[i]*A2[i];//记录多项式
for(i=0;i<=m;++i) B[i]=b[i],B2[i]=B[i]*B[i],B3[i]=B[i]*B2[i];//记录多项式
T(A,1),T(A2,1),T(A3,1),T(B,1),T(B2,1),T(B3,1);//DFT
for(i=0;i^P;++i) A[i]=A3[i]*B[i]-node(2)*A2[i]*B2[i]+A[i]*B3[i];//运算
for(T(A,-1),i=0;i<=m;++i) a[i]=A[i].x/P+0.5;//IDFT
}
};Poly<N> P;
int main()

RI i,t=0;scanf("%d%d",&n,&m),--n,--m;
for(scanf("%s",s),i=0;i<=n;++i) a[n-i]=s[i]=='*'?0:(s[i]&31);//注意A串取倒串
for(scanf("%s",s),i=0;i<=m;++i) b[i]=s[i]=='*'?0:(s[i]&31);
for(P.FFT(n,m,a,b),i=0;i<=m-n;++i) t+=!a[n+i];printf("%d\n",t);//统计个数
for(i=0;i<=m-n;++i) !a[n+i]&&printf("%d ",i+1);return 0;//输出合法位置
}

posted @ 2019-12-19 16:49  TheLostWeak  阅读(...)  评论(...编辑  收藏