# [Luogu4173/BZOJ4259] 残缺的字符串

## 题目分析：

f[i]/g[i]表示两个串的数值，当为’*’的时候，值为0，否则为与’a’的差值+1
$F\left[i\right]=\sum _{j=0}^{s-1}f\left(i-j\right)g\left(i\right)\ast \left(f\left(i-j\right)-g\left(i\right){\right)}^{2}$$F[i]=\sum_{j=0}^{s-1}f(i-j)g(i)*(f(i-j)-g(i))^2$

$F\left[i\right]==0$$F[i]==0$
$F\left[i\right]=f\left[i-j{\right]}^{3}\ast g\left[j\right]-2\ast f\left[i-j{\right]}^{2}\ast g\left[j{\right]}^{2}+f\left[i-j\right]\ast g\left[j{\right]}^{3}$$F[i]=f[i-j]^3*g[j]-2*f[i-j]^2*g[j]^2+f[i-j]*g[j]^3$

Luogu 4173
BZOJ 权限题目

## Ac 代码：

#include <cstdio>
#include <iostream>
#include <cmath>
#include <algorithm>
#define ll long long
const int maxm=300010*4;
const double PI=std::acos(-1);
struct complex{
double real,imag;
complex(){};
complex(double _real,double _imag):real(_real),imag(_imag){}
};
inline complex operator + (complex x,complex y){return (complex){x.real+y.real,x.imag+y.imag};}
inline complex operator - (complex x,complex y){return (complex){x.real-y.real,x.imag-y.imag};}
inline complex operator * (complex x,complex y){return (complex){x.real*y.real-x.imag*y.imag,x.real*y.imag+y.real*x.imag};}
int len,rev[maxm];
complex A[maxm],B[maxm];
inline void FFT(complex *a,int n,int f)
{
for(int i=0;i<n;i++) if(i<rev[i]) std::swap(a[i],a[rev[i]]);
for(int i=1;i<n;i<<=1)
{
complex wn=(complex){std::cos(PI/i),f*std::sin(PI/i)};
for(int j=0;j<n;j+=(i<<1))
{
complex w=(complex){1,0};
for(int k=0;k<i;k++,w=w*wn)
{
complex x=a[j+k];
complex y=a[i+j+k]*w;
a[j+k]=x+y;
a[i+j+k]=x-y;
}
}
}
if(f==1) return;
for(int i=0;i<n;i++) a[i].real=a[i].real/n;
}
inline void init(int n)
{
for(int i=0;i<n;i++) A[i]=(complex){0,0},B[i]=(complex){0,0};
}
double f[maxm],g[maxm];
char s[maxm],t[maxm];
ll F[maxm];
int n,m,S,T;
int ans[maxm],tot;
int main()
{
scanf("%d%d",&S,&T);
scanf("%s%s",s,t);
for(int i=0;i<S/2;i++) std::swap(s[i],s[S-i-1]);
for(int i=0;i<T;i++) f[i]=(t[i]=='*'?0:(t[i]-'a'+1.0));
for(int i=0;i<S;i++) g[i]=(s[i]=='*'?0:(s[i]-'a'+1.0));
m=S+T-2;
for(n=1;n<=m;n<<=1) len++;
for(int i=0;i<n;i++) rev[i]=(rev[i>>1]>>1)|((i&1)<<(len-1));
init(n);
for(int i=0;i<T;i++) A[i].real=f[i]*f[i]*f[i];
for(int i=0;i<S;i++) B[i].real=g[i];
FFT(A,n,1),FFT(B,n,1);
for(int i=0;i<n;i++) A[i]=A[i]*B[i];
FFT(A,n,-1);
for(int i=0;i<T;i++) F[i]=(ll)round(A[i].real);
init(n);
for(int i=0;i<T;i++) A[i].real=(f[i]*f[i]);
for(int i=0;i<S;i++) B[i].real=(g[i]*g[i]);
FFT(A,n,1),FFT(B,n,1);
for(int i=0;i<n;i++) A[i]=A[i]*B[i];
FFT(A,n,-1);
for(int i=0;i<T;i++) F[i]-=2ll*round(A[i].real);
init(n);
for(int i=0;i<T;i++) A[i].real=(f[i]);
for(int i=0;i<S;i++) B[i].real=(g[i]*g[i]*g[i]);
FFT(A,n,1),FFT(B,n,1);
for(int i=0;i<n;i++) A[i]=A[i]*B[i];
FFT(A,n,-1);
for(int i=0;i<T;i++) F[i]+=(ll)round(A[i].real);
for(int i=S-1;i<T;i++) if(!F[i]) ans[++tot]=i-S+2;
printf("%d\n",tot);
for(int i=1;i<=tot;i++) printf("%d ",ans[i]);
return 0;
}