• SD2018集训Day2 子串


    SD2018集训Day2 子串

    给定一个长度为 (m) 的串 (S),其中每个求有多少长度为 (n) 的子串 (t),满足对其作用一次排列 (p) 之后 不变,即 (t_i = t_{p_i})(S) 的字符集大小是 (c),每个字符都是一个 (1)(c) 中的数字。(n,m,cleq 5e5)

    这题是个NTT算hash,先算出每个长度为 (n) 的子串的hash值,直接把base的幂数组倒过来和字符串卷即可。(差一定倒过来卷)

    然后按排列的顺序把幂数组循环移位,再卷一下判断和原来每个串hash是否相等。

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 2e6+200; 
    int n,m,c;
    int p[N],S[N],f[N];
    int p1[N],p2[N]; 
    const int mod = 998244353;
    const int bas = 1145141;
    int lim,l,r[N*4];
    int omg[N][2];
    #define FOR(i,a,b) for(int i=a;i<=b;++i)
    int ksm(int a,int b){
    	int res=1;
    	while(b){
    		if(b&1) res=1ll*res*a%mod;
    		a=1ll*a*a%mod;b>>=1;
    	}
    	return res;
    }
    void init(){
    	omg[0][1]=1;omg[0][0]=1;
    	omg[1][1]=ksm(3,(mod-1)/lim);
    	omg[1][0]=ksm(omg[1][1],mod-2);
    	FOR(i,2,lim-1){
    		omg[i][0]=1ll*omg[i-1][0]*omg[1][0]%mod;
    		omg[i][1]=1ll*omg[i-1][1]*omg[1][1]%mod;
    	}
    	FOR(i,1,lim-1){
    		r[i]=(r[i>>1]>>1)|((i&1)?(1<<(l-1)):0);
    	}
    }
    void ntt(int *a,int opt){
    	FOR(i,0,lim-1) if(i<r[i]) swap(a[i],a[r[i]]); 
    	for(register int l=2;l<=lim;l<<=1){
    		int m=l/2;
    		for(int *g=a;g!=a+lim;g+=l){
    			for(register int i=0;i<m;++i){
    				int t=1ll*g[i+m]*omg[lim/l*i][opt]%mod;
    				g[i+m]=(g[i]-t+mod)%mod;
    				g[i]=(g[i]+t)%mod;
    			}
    		}
    	}
    	if(!opt){
    		int iv=ksm(lim,mod-2);
    		FOR(i,0,lim) a[i]=1ll*a[i]*iv%mod;
    	}
    }
    int main(){
    	freopen("sub.in", "r", stdin);
        freopen("sub.out", "w", stdout);
    	scanf("%d %d %d",&n,&m,&c);
    	FOR(i,0,n-1){
    		scanf("%d",&p[i]);p[i]--;
    	}
    	FOR(i,0,m-1){
    		scanf("%d",&S[i]);
    	}
    	f[0]=1;FOR(i,1,n-1) f[i]=1ll*f[i-1]*bas%mod; 
    	FOR(i,0,n-1) p1[n-1-i]=f[i];
    	FOR(i,0,n-1) p2[n-1-p[i]]=f[i];
    	lim=1,l=0;while(lim<2*m) lim<<=1,l++;
    	init();
    	ntt(p1,1);ntt(p2,1);ntt(S,1);
    	FOR(i,1,lim) p1[i]=(1ll*p1[i]*S[i])%mod,p2[i]=(1ll*p2[i]*S[i])%mod;
    	ntt(p1,0);ntt(p2,0);
    	FOR(i,0,m-n){
    		if(p1[i+n-1]==p2[i+n-1]){
    			printf("1");
    		}else printf("0");
    	}
    	return 0;
    }
    
  • 相关阅读:
    饿了么P7级前端工程师进入大厂的面试经验
    前端程序员面试的坑,简历写上这一条信息会被虐死!
    这次来分享前端的九条bug吧
    移动端开发必会出现的问题和解决方案
    创建一个dynamics 365 CRM online plugin (八)
    创建一个dynamics 365 CRM online plugin (七)
    创建一个dynamics 365 CRM online plugin (六)
    创建一个dynamics 365 CRM online plugin (五)
    使用User Primary Email作为GUID的问题
    怎样Debug Dynamics 365 CRM Plugin
  • 原文地址:https://www.cnblogs.com/lcyfrog/p/14263947.html
Copyright © 2020-2023  润新知