题目大意
兔子们在玩两个串的游戏。给定两个字符串S和T,兔子们想知道T在S中出现了几次,
分别在哪些位置出现。注意T中可能有“?”字符,这个字符可以匹配任何字符。
FFT
我们把T串反过来。
设a表示S串(把字符转成不为0的数字)
b表示T串,其中问号可以用一个0表示
设
c[j+m−1]=∑(a[j+i]−b[m−i−1])2∗a[j+i]∗b[m−i−1]
容易证明S串的第j个位置为开头能匹配T串则c[j+m-1]=0。
而右边的含义就是T的第i能否匹配S的第j+i。
由于贡献一定非负,最终为0一定是每一项均为0,也就是匹配成功。
后面的拆一下可以做三次FFT完成。
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
typedef double db;
const db pi=acos(-1);
const int maxn=530000+10;
struct node{
db x,y;
friend node operator +(node a,node b){
node c;
c.x=a.x+b.x;c.y=a.y+b.y;
return c;
}
friend node operator -(node a,node b){
node c;
c.x=a.x-b.x;c.y=a.y-b.y;
return c;
}
friend node operator *(node a,node b){
node c;
c.x=a.x*b.x-a.y*b.y;c.y=a.x*b.y+a.y*b.x;
return c;
}
};
node a[maxn],b[maxn],c[maxn],d[maxn],e[maxn],f[maxn],tt[maxn],w[maxn];
int rev[maxn],ans[maxn];
db ce;
char s[maxn],h[maxn];
int i,j,k,l,t,n,m,mx,len,top;
int pow(int x,int y){
if (y==2) return x*x;
else return x*x*x;
}
void prepare(){
w[0].x=1;w[0].y=0;
w[1].x=cos(2*pi/len);w[1].y=sin(2*pi/len);
fo(i,2,len) w[i]=w[i-1]*w[1];
fo(i,0,len-1){
int p=0;
for (int j=0,tp=i;j<ce;j++,tp/=2) p=(p<<1)+(tp%2);
rev[i]=p;
}
}
void DFT(node *a,int sig){
int i;
fo(i,0,len-1) tt[rev[i]]=a[i];
for (int m=2;m<=len;m*=2){
int half=m/2,bei=len/m;
fo(i,0,half-1){
node wi=sig>0?w[i*bei]:w[len-i*bei];
for (int j=i;j<len;j+=m){
node u=tt[j],v=tt[j+half]*wi;
tt[j]=u+v;
tt[j+half]=u-v;
}
}
}
if (sig==-1)
fo(i,0,len-1) tt[i].x/=len;
fo(i,0,len-1) a[i]=tt[i];
}
void FFT(node *a,node *b,node *c){
int i;
fo(i,0,len-1) e[i]=a[i],f[i]=b[i];
DFT(e,1);DFT(f,1);
fo(i,0,len-1) e[i]=e[i]*f[i];
DFT(e,-1);
fo(i,0,len-1) c[i]=e[i];
}
int main(){
//freopen("4503.in","r",stdin);
scanf("%s",s);
n=strlen(s);
scanf("%s",h);
m=strlen(h);
mx=max(n,m);
len=1;
while (len<mx*2) len*=2;
ce=log(len)/log(2);
prepare();
reverse(h,h+m);
fo(i,0,n-1)
a[i].x=pow(s[i]-'a'+1,3);
fo(i,0,m-1)
b[i].x=(h[i]=='?'?0:h[i]-'a'+1);
FFT(a,b,d);
fo(i,0,len-1) c[i]=c[i]+d[i];
fo(i,0,n-1)
a[i].x=-2*pow(s[i]-'a'+1,2);
fo(i,0,m-1)
b[i].x=pow(h[i]=='?'?0:h[i]-'a'+1,2);
FFT(a,b,d);
fo(i,0,len-1) c[i]=c[i]+d[i];
fo(i,0,n-1)
a[i].x=s[i]-'a'+1;
fo(i,0,m-1)
b[i].x=pow(h[i]=='?'?0:h[i]-'a'+1,3);
FFT(a,b,d);
fo(i,0,len-1) c[i]=c[i]+d[i];
fo(i,0,n-m)
if (int(c[i+m-1].x)==0) ans[++top]=i;
printf("%d\n",top);
fo(i,1,top) printf("%d\n",ans[i]);
}