首先将t串反写,然后用
首先令
fk=∑i+j=k(ai−bj)2×ai×bj
可以发现若fk=0,则s[k−lent+1..k]可以和t的反串(其实就是一开始的正串)匹配成功。
然后我们只要快速求fk就行了。
fk=∑a3i×bj+∑ai×b3j−2∑a2i×b2j
然后FFT求出三个卷积看看是否为0就可以了。
(最近写代码越来越喜欢空行了smg
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
const double PI=acos(-1);
const int N=100005;
int n,len,lem;
int ans[N],ans1[N],ans2[N],ans3[N],A[N],B[N];
int rev[N<<2];
char s[N],t[N];
struct C
{
double real,i;
C (double a=0,double b=0) {real=a,i=b;}
C operator + (C a) {return C(real+a.real,i+a.i);}
C operator - (C a) {return C(real-a.real,i-a.i);}
C operator * (C a) {return C(real*a.real-i*a.i,real*a.i+i*a.real);}
};
C a[N<<2],b[N<<2],c1[N<<2],c2[N<<2],c3[N<<2];
inline void FFT(C x[],int T)
{
for (int i=0;i<n;i++)
if (rev[i]<i) swap(x[rev[i]],x[i]);
for (int i=2;i<=n;i<<=1)
{
C wn(cos(2*PI/i),T*sin(2*PI/i));
for (int j=0;j<n;j+=i)
{
C t,tmp,w(1,0);
for (int k=0;k<i>>1;k++)
{
tmp=x[j+k];
t=w*x[j+k+(i>>1)];
x[j+k]=tmp+t;
x[j+k+(i>>1)]=tmp-t;
w=w*wn;
}
}
}
}
int main()
{
scanf("%s",s);
scanf("%s",t);
len=strlen(s); lem=strlen(t);
int m=len<<1; n=1;
while (n<m) n<<=1;
for (int i=0;i<n;i++)
rev[i]=(rev[i>>1]>>1)|((i&1)?n>>1:0);
for (int i=0;i<len;i++)
A[i]=s[i]-'a'+1;
for (int i=0;i<lem;i++)
B[i]=(t[lem-i-1]=='?')?0:t[lem-i-1]-'a'+1;
for (int i=0;i<len;i++)
a[i]=A[i]*A[i]*A[i];
for (int i=0;i<lem;i++)
b[i]=B[i];
FFT(a,1); FFT(b,1);
for (int i=0;i<n;i++)
c1[i]=a[i]*b[i];
FFT(c1,-1);
for (int i=0;i<len;i++)
ans1[i]=(int)(c1[i].real/(double)n+0.5);
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
for (int i=0;i<len;i++)
a[i]=A[i];
for (int i=0;i<lem;i++)
b[i]=B[i]*B[i]*B[i];
FFT(a,1); FFT(b,1);
for (int i=0;i<n;i++)
c2[i]=a[i]*b[i];
FFT(c2,-1);
for (int i=0;i<len;i++)
ans2[i]=(int)(c2[i].real/(double)n+0.5);
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
for (int i=0;i<len;i++)
a[i]=A[i]*A[i];
for (int i=0;i<lem;i++)
b[i]=B[i]*B[i];
FFT(a,1); FFT(b,1);
for (int i=0;i<n;i++)
c3[i]=a[i]*b[i];
FFT(c3,-1);
for (int i=0;i<len;i++)
ans3[i]=(int)(c3[i].real/(double)n+0.5);
for (int i=lem-1;i<len;i++)
if (ans1[i]+ans2[i]-2*ans3[i]==0) ans[++ans[0]]=i;
printf("%d\n",ans[0]);
for (int i=1;i<=ans[0];i++)
printf("%d\n",ans[i]-lem+1);
return 0;
}