zoukankan      html  css  js  c++  java
  • 多项式卷积做字符串匹配小结

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

    参考思路

    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<<'
    ';
    		for (int i=1; i<=n; ++i) if (av[i]) cout<<i<<" ";
    		cout<<'
    ';
    	}
    }
    
  • 相关阅读:
    8.16集训
    8.15集训
    Educational Codeforces Round 97 (Rated for Div. 2)
    Codeforces Round #679 (Div. 2, based on Technocup 2021 Elimination Round 1)
    尺取法
    Codeforces Round #677 (Div. 3)
    单调队列
    dfs序
    离散化
    [kuangbin带你飞]专题七 线段树
  • 原文地址:https://www.cnblogs.com/Yuhuger/p/13746847.html
Copyright © 2011-2022 走看看