多项式卷积做字符串匹配小结
感觉就是把若干个博客抄在了一起,供自己回忆用
参考思路
1.普通KMP平方卷积,拆项处理
2.带通配符KMP平方卷积乘上不为通配符,拆项处理
问题的另一种思路,如果使用FFT,另外可以对复数做文章,参考链接1
参考链接
1.https://www.cnblogs.com/Saurus/p/6349419.html
2.https://blog.csdn.net/CCCCTong/article/details/104565258/
3.https://www.cnblogs.com/GreenDuck/p/10585871.html
一道题
https://codeforces.com/problemset/problem/827/E
代码
#include <bits/stdc++.h>
using namespace std;
const int M=998244353;
const int G=3;
const int N=3000000;
int t,n;
char s[N];
int a[N],b[N],a2[N],b2[N];
bool av[N];
typedef long long ll;
namespace{
int mul(int x,int y){
return (ll)x*y%M;
}
int add(int x,int y){
return (x+=y)>=M?x-M:x;
}
int sub(int x,int y){
return (x-=y)<0?x+M:x;
}
int sqr(int x){
return mul(x,x);
}
int fp(int x,int y){
int ret=1;
for (; y; y>>=1,x=mul(x,x))
if (y&1) ret=mul(ret,x);
return ret;
}
}
void DFT(int P[],int n,int oper){
for (int i=1,j=0; i<n-1; ++i){
for (int s=n; j^=s>>=1,~j&s;);
if (i<j) swap(P[i],P[j]);
}
for (int d=0; (1<<d)<n; ++d){
int m=1<<d,m2=m*2;
int unit_p0=fp(G,(M-1)/m2);
//cerr<<"unit_p0"<<m2<<" "<<unit_p0<<endl;
if (oper<0) unit_p0=fp(unit_p0,M-2);
for (int i=0; i<n; i+=m2){
int unit=1;
for (int j=0; j<m; ++j){
int &P1=P[i+j+m],&P2=P[i+j];
int t=(ll)unit*P1%M;
P1=sub(P2,t);
P2=add(P2,t);
unit=(ll)unit*unit_p0%M;
}
}
}
if (oper<0){
int inv=fp(n,M-2);
for (int i=0; i<n; ++i) P[i]=mul(P[i],inv);
}
}
void print(int *a,int l,int r){
for (int i=l; i<r; ++i) cerr<<a[i]<<" ";
cerr<<endl;
}
int main(){
scanf("%d",&t);
while (t--){
scanf("%d",&n);
int lim=1;
for (; lim<n+n; lim<<=1);
memset(a,0,lim*sizeof(*a));
memset(b,0,lim*sizeof(*b));
memset(a2,0,lim*sizeof(*a2));
memset(b2,0,lim*sizeof(*b2));
scanf("%s",s);
for (int i=0; i<n; ++i){
//cerr<<s[i]<<endl;
switch (s[i]){
case '?':a[i]=0; break;
case 'V':a[i]=M-1; break;
default:a[i]=1;
}
}
memcpy(b,a,n*sizeof(*a));
reverse(b,b+n);
for (int i=0; i<n; ++i) a2[i]=mul(a[i],a[i]);
for (int i=0; i<n; ++i) b2[i]=mul(b[i],b[i]);
DFT(a,lim,1);
DFT(b,lim,1);
DFT(a2,lim,1);
DFT(b2,lim,1);
for (int i=0; i<lim; ++i){
int x=mul(mul(a2[i],b2[i]),2);
int y=mul(mul(a[i],b[i]),2);
a[i]=sub(x,y);
}
DFT(a,lim,-1);
//print(a,0,lim);
for (int i=1; i<=n; ++i) av[i]=0;
av[n]=1;
for (int i=n; i<n-1+n; ++i) av[i-n+1]=(a[i]==0);
for (int i=1; i<=n; ++i)
for (int j=i+i; j<=n; j+=i) av[i]&=av[j];
int cnt=0;
for (int i=1; i<=n; ++i) cnt+=av[i];
cout<<cnt<<'\n';
for (int i=1; i<=n; ++i) if (av[i]) cout<<i<<" ";
cout<<'\n';
}
}