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;
}

Codeforces 1466G - Song of the Sirens(哈希)的更多相关文章

  1. Codeforces Gym 100338B Spam Filter 字符串哈希+贝叶斯公式

    原题链接:http://codeforces.com/gym/100338/attachments/download/2136/20062007-winter-petrozavodsk-camp-an ...

  2. 【CodeForces】961 F. k-substrings 字符串哈希+二分

    [题目]F. k-substrings [题意]给定长度为n的串S,对于S的每个k-子串$s_ks_{k+1}...s_{n-k+1},k\in[1,\left \lceil \frac{n}{2} ...

  3. Codeforces 542D Superhero's Job 数论 哈希表 搜索

    原文链接https://www.cnblogs.com/zhouzhendong/p/CF542D.html 题目传送门 - CF542D 题目传送门 - 51Nod1477 题意 定义公式 $J(x ...

  4. Codeforces Round #543 (Div. 2) F dp + 二分 + 字符串哈希

    https://codeforces.com/contest/1121/problem/F 题意 给你一个有n(<=5000)个字符的串,有两种压缩字符的方法: 1. 压缩单一字符,代价为a 2 ...

  5. Codeforces 1182D Complete Mirror [树哈希]

    Codeforces 中考考完之后第一个AC,纪念一下qwq 思路 简单理解一下题之后就可以发现其实就是要求一个点,使得把它提为根之后整棵树显得非常对称. 很容易想到树哈希来判结构是否相同,而且由于只 ...

  6. Codeforces 356E - Xenia and String Problem(哈希)

    Codeforces 题面传送门 & 洛谷题面传送门 首先显然一个 gray 串的长度只可能是 \(2^k-1\),其中 \(k\in\mathbb{Z}\). 考虑将一个字符改成另外一个字符 ...

  7. Codeforces 961F - k-substrings(二分+哈希)

    Codeforces 题面传送门 & 洛谷题面传送门 介绍一种奇怪的 \(\Theta(n\log n)\) 的奇怪做法. 注意到这个"border 的长度必须是奇数"的条 ...

  8. Codeforces 1340F - Nastya and CBS(分块+哈希)

    Codeforces 题面传送门 & 洛谷题面传送门 首先看到这样的数据范围我们可以考虑分块,具体来说,对于每一块我们记录其中的括号是否能完全消掉,以及对其进行括号相消之后的括号序列(显然是一 ...

  9. Codeforces 109D String Transformation 字符串 哈希 KMP

    原文链接https://www.cnblogs.com/zhouzhendong/p/CF109D.html 题目传送门 - CF109D 题意 给定两个字符串 $a,b$ ,求一组 $i,j$ 使得 ...

随机推荐

  1. 无网环境安装docker之--rpm

    总体思路:找一台可以联网的linux,下载docker的RPM依赖包而不进行安装(yum localinstall),将所有依赖的rpm环境打包好,再在无网环境中解压逐一安装(rpm:  --forc ...

  2. sql常用的统计公式

    hivesql中max,min函数不能作用于多列,因此在有上下门限区间限制时多用公式直接计算. max(x,y)=(x+y+ABS(x-y))/2 min(x,y)=(x+y-ABS(x-y))/2 ...

  3. Vulnhub实战-FALL靶机👻

    Vulnhub实战-FULL靶机 下载地址:http://www.vulnhub.com/entry/digitalworldlocal-fall,726/ 1.描述 通过描述我们可以知道这个靶机枚举 ...

  4. Python学习系列之一: python相关环境的搭建

    前言 学习python和使用已经一年多了,这段时间抽空整理了一下以前的笔记,方便日后查阅. Python介绍 Python 是一个高层次的结合了解释性.编译性.互动性和面向对象的脚本语言. Pytho ...

  5. 【UE4】GamePlay架构

    新标签打开或者下载看大图 更新: 增加 编程子系统 Subsystem 思维导图 Character pipeline

  6. 【UE4 设计模式】工厂方法模式 Factory Method Pattern 及自定义创建资源

    概述 描述 又称为工厂模式,也叫虚拟构造器(Virtual Constructor)模式,或者多态工厂(Polymorphic Factory)模式 工厂父类负责定义创建产品对象的公共接口,而工厂子类 ...

  7. Vue报错 type check failed for prop “xxx“. Expected String with value “xx“,got Number with value ‘xx‘

    vue报错    [Vue warn]: Invalid prop: type check failed for prop "name". Expected String with ...

  8. Noip模拟4(忁靈霁) 2021.6.6

    T1 随(Rand) 由杠哥大定理可得,这题目前不可做,先跳走啦,咕咕.... T2 单(single) 考场上,简单看一眼就看出是个高斯消元,然后..... 板子没记住!!! 然而这不是最糟糕的.. ...

  9. Linux Shell Here Document

    Here Document 是一种有特殊用处的代码块,他使用IO重定向的形式记录了一段临时的文本或交互命令,并且把这些文本或命令 依次的传递给一个程序或一个命令,作为他运行时的标准输入. Here d ...

  10. reorder-list leetcode C++

    Given a singly linked list L: L 0→L 1→-→L n-1→L n, reorder it to: L 0→L n →L 1→L n-1→L 2→L n-2→- You ...