标签:== tor swa 16px abs str class ret std
$\newcommand{align}[1]{\begin{align*}#1\end{align*}}$如果$S_{i\cdots i+m-1}$与$T$相等,那么$\align{\sum\limits_{j=0}^{m-1}\left(S_{i+j}-T_j\right)^2T_j}=0$(令通配符为$T_i=0$),展开得到$\align{\sum\limits_{j=0}^{m-1}S^2_{i+j}T_j-2\sum\limits_{j=0}^{m-1}S_{i+j}T^2_j+\sum\limits_{j=0}^{m-1}T_j^3}$,这种错位相乘直接翻转卷积即可
这大概是一个套路...学习之
#include<stdio.h>
#include<math.h>
#include<string.h>
typedef double du;
const du eps=1e-5;
struct complex{
du x,y;
complex(du a=0,du b=0){x=a;y=b;}
};
complex operator+(complex a,complex b){return complex(a.x+b.x,a.y+b.y);}
complex operator-(complex a,complex b){return complex(a.x-b.x,a.y-b.y);}
complex operator*(complex a,complex b){return complex(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);}
template<class T>void swap(T&a,T&b){
T c=a;
a=b;
b=c;
}
int rev[262144],N;
void pre(int n){
int i,k;
for(N=1,k=0;N<n;N<<=1)k++;
for(i=0;i<N;i++)rev[i]=(rev[i>>1]>>1)|((i&1)<<(k-1));
}
void fft(complex*a,int on){
int i,j,k;
complex t;
for(i=0;i<N;i++){
if(i<rev[i])swap(a[i],a[rev[i]]);
}
for(i=2;i<=N;i<<=1){
for(j=0;j<N;j+=i){
for(k=0;k<i>>1;k++){
t=complex(cos(k*M_PI/(i/2)),on*sin(k*M_PI/(i/2)))*a[i/2+j+k];
a[i/2+j+k]=a[j+k]-t;
a[j+k]=a[j+k]+t;
}
}
}
if(on==-1){
for(i=0;i<N;i++)a[i].x/=N;
}
}
char s[100010],t[100010];
complex a[262144],b[262144],c[262144],d[262144];
int main(){
int n,m,i,x,ans;
double t3;
scanf("%s%s",s,t);
n=strlen(s);
m=strlen(t);
for(i=0;i>1;i++)swap(s[n-1-i],s[i]);
for(i=0;i<n;i++){
x=s[i]-‘a‘+1;
a[i].x=x*x;
c[i].x=x;
}
t3=0;
for(i=0;i<m;i++){
if(t[i]==‘?‘)
x=0;
else
x=t[i]-‘a‘+1;
b[i].x=x;
d[i].x=x*x;
t3+=x*x*x;
}
pre(n<<1);
fft(a,1);
fft(b,1);
for(i=0;i<N;i++)a[i]=a[i]*b[i];
fft(a,-1);
fft(c,1);
fft(d,1);
for(i=0;i<N;i++)b[i]=c[i]*d[i];
fft(b,-1);
ans=0;
for(i=0;i<=n-m;i++){
if(fabs((a[n-1-i]-b[n-1-i]*2+t3).x)<=eps)ans++;
}
printf("%d\n",ans);
for(i=0;i<=n-m;i++){
if(fabs((a[n-1-i]-b[n-1-i]*2+t3).x)<=eps)printf("%d\n",i);
}
}
标签:== tor swa 16px abs str class ret std
原文地址:https://www.cnblogs.com/jefflyy/p/8920498.html