ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Codeforces 1466G - Song of the Sirens(哈希)

2021-10-19 21:02:20  阅读:181  来源: 互联网

标签:Sirens const Song int text occ Codeforces MAXN 要么


Codeforces 题面传送门 & 洛谷题面传送门

事实证明,有的难度评分不算很高、涉及的知识点不算很难的题目也能出得非常神仙

首先考虑如何暴力求答案。注意到一个文本串 \(T\) 在 \(s_k\) 中出现的位置,有两种可能,要么跨过中间的 \(t_k\),要么没跨过,前者等价于文本串在 \(s_{k-1}[|s_{k-1}|-|T|+2,|s_{k-1}|]+t_k+s_{k-1}[1,|T|-1]\) 中出现的次数。由于其长度为 \(\mathcal O(|T|)\),因此可以在 KMP 或哈希在 \(\mathcal O(|T|)\) 时间内求出。要么没有跨过中间的 \(t_k\),而这样的出现位置要么在 \(s_0\) 中出现过,要么在某个 \(s_{k'}(k'<k)\) 中作为跨过中间的 \(t_{k'}\) 的字符串出现。因此

\[res=\text{occ}(t_0,T)·2^k+\sum\limits_{i=1}^k\text{occ}(s_{i}[|s_{i}|-|T|+2,|s_{i}|]+t_i+s_{i}[1,|T|-1],T)·2^{k-i} \]

其中 \(\text{occ}(s,t)\) 表示 \(t\) 在 \(s\) 中的出现次数。

考虑优化。我们找到最小的 \(k'\),满足 \(|t_{k'}|>|T|\),如果不存在这样的 \(k'\) 或 \(k'>k\) 则直接输出 \(\text{occ}(t_k,T)\) 即可。否则我们先令答案加上 \(\text{occ}(t_{k'},T)·2^{k-k'}\),而对于 \(i>k',j>k'\),由于 \(|T|<|s_i|,|T|<|s_j|\),如果 \(t_i=t_j\),那么显然有 \(s_{i}[|s_{i}|-|T|+2,|s_{i}|]+t_i+s_{i}[1,|T|-1]=s_{j}[|s_{j}|-|T|+2,|s_{j}|]+t_j+s_{j}[1,|T|-1]\),我们考虑枚举所有 \(t_j=c\),计算 \(\text{occ}(s_{i}[|s_{i-1}|-|T|+2,|s_{i}|]+c+s_{i}[1,|T|-1],T)\),然后前缀和求出 \(\sum\limits_{i=k'+1}^k2^{-i}[t_i=c]\),这样即可在 \(|T|·|\Sigma|\) 的时间内算出答案。

时间复杂度 \(\Theta((\sum|T|+n)·|\Sigma|)\)

const int MAXN=1e5;
const int MAXM=100;
const int MAXL=1e6;
const int BS=191;
const int MOD=1e9+7;
const int INV2=5e8+4;
const int HMOD=1004535809;
int n,qu,occ[MAXN+5][28],pw[MAXN+5],ipw[MAXN+5],pw_hs[MAXL+5];
char s[MAXM+5],t[MAXN+5];string str[22];
int getocc(string s,string t){
	static int hss[MAXL*2+5];int hst=0,res=0;
	for(int i=1;i<=s.size();i++) hss[i]=(1ll*hss[i-1]*BS+s[i-1])%HMOD;
	for(int i=0;i<t.size();i++) hst=(1ll*BS*hst+t[i])%HMOD;
	for(int i=0;i+t.size()<=s.size();i++)
		if((hss[i+t.size()]-1ll*pw_hs[t.size()]*hss[i]%HMOD+HMOD)%HMOD==hst)
			res++;
	return res;
}
int main(){
	scanf("%d%d%s%s",&n,&qu,s+1,t+1);
	for(int i=(pw[0]=ipw[0]=1);i<=MAXN;i++){
		ipw[i]=1ll*ipw[i-1]*INV2%MOD;
		pw[i]=(pw[i-1]<<1)%MOD;
	}
	for(int i=(pw_hs[0]=1);i<=MAXL;i++) pw_hs[i]=1ll*pw_hs[i-1]*BS%HMOD;
	for(int i=1;i<=n;i++){
		for(int j=0;j<26;j++) occ[i][j]=occ[i-1][j];
		occ[i][t[i]-'a']=(occ[i][t[i]-'a']+ipw[i])%MOD;
	}
	int len=strlen(s+1),cur=0;for(int i=1;i<=len;i++) str[0].pb(s[i]);
	while(str[cur].size()<=MAXL&&cur<n){
		cur++;
		for(int i=0;i<str[cur-1].size();i++) str[cur].pb(str[cur-1][i]);
		str[cur].pb(t[cur]);
		for(int i=0;i<str[cur-1].size();i++) str[cur].pb(str[cur-1][i]);
	}
	while(qu--){
		int k;string p;static char buf[MAXL+5];
		scanf("%d%s",&k,buf+1);int L=strlen(buf+1);
		for(int i=1;i<=L;i++) p.pb(buf[i]);
		int mx=0;while(str[mx].size()<=L) mx++;
		if(k<=mx){printf("%d\n",getocc(str[k],p));continue;}
		int res=1ll*getocc(str[mx],p)*pw[k-mx]%MOD;
		for(int i=0;i<26;i++){
			string nw_s;
			for(int j=str[mx].size()-L+1;j<str[mx].size();j++) nw_s.pb(str[mx][j]);
			nw_s.pb(i+'a');
			for(int j=0;j<L-1;j++) nw_s.pb(str[mx][j]);
			int msk=occ[k][i],cnt=getocc(nw_s,p);
//			printf("%d %d\n",msk,cnt);
//			cout<<nw_s<<" "<<p<<endl;
			for(int j=1;j<=mx;j++) if(t[j]-'a'==i) msk=(msk-ipw[j]+MOD)%MOD;
			res=(res+1ll*msk*pw[k]%MOD*cnt)%MOD;
		} printf("%d\n",res);
	}
	return 0;
}

标签:Sirens,const,Song,int,text,occ,Codeforces,MAXN,要么
来源: https://www.cnblogs.com/ET2006/p/Codeforces-1466G.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有