多项式卷积做字符串匹配小结

感觉就是把若干个博客抄在了一起,供自己回忆用

参考思路

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';
	}
}
posted @ 2020-09-28 20:54  Yuhuger  阅读(157)  评论(0编辑  收藏  举报