定义完全匹配函数:
则有
设多项式,则
那么
表示A串中以结尾长度为的子串和串匹配
然后用计算多项式
这一题还需要再输出一行串的数组。
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=(1<<21)+7,mod=998244353;
inline int qpow(int x,int y) {
int res(1);
while(y) {
if(y&1) res=1LL*res*x%mod;
x=1LL*x*x%mod;
y>>=1;
}
return res;
}
int r[maxn];
inline void ntt(int *x,int lim,int opt) {
int i,j,k,m,gn,g,tmp;
for(i=0; i<lim; ++i)
if(i<r[i]) swap(x[i],x[r[i]]);
for(m=2; m<=lim; m<<=1) {
k=m>>1;
gn=qpow(3,(mod-1)/m);
for(i=0; i<lim; i+=m) {
g=1;
for(j=0; j<k; ++j,g=1LL*g*gn%mod) {
tmp=1LL*x[i+j+k]*g%mod;
x[i+j+k]=(x[i+j]-tmp+mod)%mod;
x[i+j]=(x[i+j]+tmp)%mod;
}
}
}
if(opt==-1) {
reverse(x+1,x+lim);
int inv=qpow(lim,mod-2);
for(i=0; i<lim; ++i) x[i]=1LL*x[i]*inv%mod;
}
}
int A[maxn],B[maxn],f[maxn/2],Next[maxn/2],n,m,k,lim(1);
char a[maxn/2],b[maxn/2];
void getfail() {
Next[0]=Next[1]=0;
for(int i=1,j;b[i];++i) {
j=Next[i];
while(j&&b[i]!=b[j]) j=Next[j];
Next[i+1]=(b[i]==b[j])?j+1:0;
}
}
int main() {
scanf("%s%s",a,b);
n=strlen(a),m=strlen(b);//n>m
while(lim<(n<<1)) lim<<=1;
for(int i=0; i<lim; ++i) r[i]=(i&1)*(lim>>1)+(r[i>>1] >> 1);
for(int i=0;i<n;++i) A[i]=a[i]-'a'+1;
for(int i=0;i<m;++i) B[i]=b[m-1-i]-'a'+1;
int sum(0);
for(int i=0;i<m;++i) sum+=B[i]*B[i];
f[0]=A[0]*A[0];
for(int i=1;i<n;++i) f[i]=f[i-1]+A[i]*A[i];
ntt(A,lim,1),ntt(B,lim,1);
for(int i=0; i<lim; ++i) A[i]=1LL*A[i]*B[i]%mod;
ntt(A,lim,-1);
vector<int>ans;
for(int i=m-1;i<lim;++i) {
int p=f[i]-f[i-m]-2*A[i]+sum;
if(!p) ans.emplace_back(i-m+2);
}
// cout<<ans.size()<<'\n';
for(int i:ans) {
cout<<i<<'\n';
}
getfail();
for(int i=1;i<=m;++i) cout<<Next[i]<<' ';
return 0;
}