2018.11.17 bzoj4259: 殘缺的字串(fft)
阿新 • • 發佈:2018-11-25
傳送門
套路題。
我們把
~
對映成
~
,然後把
對映成
。
考慮對於兩個長度都為
的字串
。
我們定義一個差異函式
其中
是
的字元的對映值。
然後如果
說明兩個字串可以匹配。
然後我們用
把原題中給出的第一個字串的長度補成
,再翻轉一下。
然後將兩個序列卷積一下可以求出對於第二個串匹配起點在
時分別的
值。
只需要看哪些位是
就行了。
程式碼:
#include<bits/stdc++.h>
#define ri register int
using namespace std;
typedef long long ll;
const double pi=acos(-1.0);
const int N=2e6+5;
int tim=0,lim=1,n,m,A[N],B[N],pos[N];
ll sum[N];
vector<int>ans;
char s[N];
struct Complex{
double x,y;
inline Complex operator+(const Complex&b){return (Complex){x+b.x,y+b.y};}
inline Complex operator-(const Complex&b){return (Complex){x-b.x,y-b.y};}
inline Complex operator*(const Complex&b){return (Complex){x*b.x-y*b.y,y*b.x+b.y*x};}
inline Complex operator/(const double&b){return (Complex){x/b,y/b};}
}a[N],b[N];
inline void fft(Complex *a,int type){
for(ri i=0;i<lim;++i)if(i<pos[i])swap(a[i],a[pos[i]]);
for(ri mid=1;mid<lim;mid<<=1){
Complex wn=(Complex){cos(pi/mid),type*sin(pi/mid)};
for(ri j=0,len=mid<<1;j<lim;j+=len){
Complex w=(Complex){1,0};
for(ri k=0;k<mid;++k,w=w*wn){
Complex a0=a[j+k],a1=w*a[j+k+mid];
a[j+k]=a0+a1,a[j+k+mid]=a0-a1;
}
}
}
if(type==-1)for(ri i=0;i<lim;++i)a[i]=a[i]/lim;
}
inline void solve1(){
for(ri i=0;i<=n;++i)a[i].x=A[i]*A[i]*A[i],b[i].x=B[i];
fft(a,1),fft(b,1);
for(ri i=0;i<lim;++i)a[i]=a[i]*b[i];
fft(a,-1);
for(ri i=0;i<lim;++i)sum[i]+=(ll)(a[i].x+0.5),a[i].x=a[i].y=b[i].x=b[i].y=0;
}
inline void solve2(){
for(ri i=0;i<=n;++i)a[i].x=A[i]*A[i],b[i].x=B[i]*B[i],a[i].y=b[i].y=0;
fft(a,1),fft(b,1);
for(ri i=0;i<lim;++i)a[i]=a[i]*b[i];
fft(a,-1);
for(ri i=0;i<lim;++i)sum[i]-=2ll*(ll)(a[i].x+0.5),a[i].x=a[i].y=b[i].x=b[i].y=0;
}
inline void solve3(){
for(ri i=0;i<=n;++i)a[i].x=A[i],b[i].x=B[i]*B[i]*B[i],a[i].y=b[i].y=0;
fft(a,1),fft(b,1);
for(ri i=0;i<lim;++i)a[i]=a[i]*b[i];
fft(a,-1);
for(ri i=0;i<lim;++i)sum[i]+=(ll)(a[i].x+0.5),a[i].x=a[i].y=b[i].x=b[i].y=0;
}
int main(){
int ml;
scanf("%d%d",&m,&n),ml=m+n,--m,--n;
scanf("%s",s);
for(ri i=0;i<=m;++i)A[i]=s[i]=='*'?0:s[i]-'a'+1;
reverse(A,A+m+1);
scanf("%s",s);
for(ri i=0;i<=n;++i)B[i]=s[i]=='*'?0:s[i]-'a'+1;
while(lim<=ml)lim<<=1,++tim;
for(ri i=0;i<lim;++i)pos[i]=(pos[i>>1]>>1)|((i&1)<<(tim-1));
solve1(),solve2(),solve3();
for(ri i=m,j=1;i<=n;++i,++j)if(!sum[i])ans.push_back(j);
printf("%d\n",ans.size());
for(ri i=0;i<ans.size();++i)printf("%d ",ans[i]);
return 0;
}