CF1466G Song of the Sirens
题意简述:给出 \(n,s_0,t\ (n=|t|)\),定义 \(s_i=s_{i-1}+t_i+s_{i-1}\)。多次询问给出 \(k,m\),求 \(m\) 在 \(s_k\) 中的出现次数。记 \(L=\sum |m|\),则 \(L\leq 10^6\)。
Goodbye 2020 的 G。我当时怎么没做出来呢?
key observation:若 \(|m|\leq|s_i|\),那么答案可以分成两部分计算:
- 一部分是 \(m\) 完整地出现在 \(s_k\) 中的次数。那么根据 \(s\) 的定义,设 \(m\) 在 \(s_i\) 中出现了 \(f(m,s_i)\) 次,则 \(m\) 在 \(s_k\) 中出现了 \(2^{k-i}f(m,s_i)\) 次。这一点是显然的。
- 另一部分是 \(m\) 中有一个字符被 \(t_{i+1},t_{i+2},\cdots,t_k\) 的某个字符匹配,剩下来的前缀出现在 \(s_i\) 的后缀,后缀出现在 \(s_i\) 的前缀的次数之和。考虑 \(t\) 的某个位置 \(p\ (i<p\leq k)\) 上的字符 \(t_p\) 在 \(s_k\) 中被复制的次数(只考虑该位置 \(p\),而不考虑与 \(t_p\) 相同的其它位置上的字符),根据 \(s\) 的定义,它被复制了 \(2^{k-p}\) 次。枚举 \(m\) 中被匹配的位置 \(j\) 和 \(t[i+1:k]\) 中与 \(m_j\) 匹配的位置 \(p\),则贡献可以写成 \(\sum_{j=1}^{|m|}\sum_{p=i+1}^k2^{k-p}[m[1:j-1]=s_i[|s_i|-j+1:|s_i|]\land m_j=t_p\land m[j+1:r]=s_i[1:r-j]]\)。将其改写为 \(\sum_{j=1}^{|m|}[m[1:j-1]=s_i[|s_i|-j+1:|s_i|]\land m[j+1:r]=s_i[1:r-j]]\sum_{p=i+1}^k2^{k-p}[m_j=t_p]\)。注意到后面这坨东西在 \(i,k\) 确定的情况下,对于相同的 \(m_j\) 给出的答案是相同的。因为 \(m_j\) 的取值只有 \(26\) 种,那么预处理出来即可。
- 怎么预处理?注意到相同的 \(t_p\) 对于不同的 \(i,k\) 贡献可能不同,很讨厌。将其写为 \(\dfrac{\sum_{p=i+1}^n2^{n-p}[m_j=t_p]-\sum_{p=k+1}^n2^{n-p}[m_j=t_p]}{2^{n-k}}\),那么对于每个字符 \(c\),预处理出 \(g(c,i)=\sum_{p=i+1}^n2^{n-p}[t_p=c]\) 与 \(2\) 的幂的逆元,就可以 \(\mathcal{O}(1)\) 计算上式(\(\dfrac{g(m_j,i+1)-g(m_j,k+1)}{2^{n-k}}\))。即对于每个字符 \(c\) 和字符串编号 \(i\),预处理出在 \(t[i+1:n]\) 中所有与 \(c\) 相等的 \(t_p\) 在 \(s_n\) 中被复制的次数,就可以快速计算在 \(t[i+1:k]\) 中所有与 \(c\) 相等的 \(t_p\) 在 \(s_k\) 中被复制的次数。
思路 1:找到一个最小的 \(pos\) 使得 \(|s_{pos}|\geq \max(|m|)\)(如果不存在则为 \(n\))。对于每一个 \(j\in[0,pos]\),建出 \(s_j\) 的后缀数组,然后处理所有 \(k=j\) 的询问(若 \(j=pos\) 则处理所有 \(k\geq j\) 的询问)即可(SA 的主要作用是求出 \(m\) 在 \(s_i\) 中的出现次数)。判断 \(m,s\) 的前缀后缀是否相等需要用哈希。时间复杂度 \(\mathcal{O}(L\log L)\)。常数较大(而且我还写挂了)。
思路 2:在上面的思路中,对于一个询问,我们主要关注的是它的 \(k\)。这样在求出现次数的时候必须使用后缀数据结构(因为如果有很多 \(k\) 都很大而 \(|m|\) 很小的询问,同时有一个 \(|m|\) 很大的询问,那么直接哈希判断的复杂度可以达到 \(qL\)),比较麻烦。但是注意到对于那些 \(|m|\) 很小的询问,我们没有必要让它与 \(s_{pos}\) 匹配,直接找到一个最小的 \(i\) 满足 \(|s_i|\geq |m|\),让它与 \(s_i\) 匹配就好了。如果 \(i>k\) 则显然没有出现(因为 \(|s_k|<|m|\))。这样求出现次数就可以直接哈希或者 KMP 了,查询的时间复杂度可以降为 \(\mathcal{O}(L)\)。总时间复杂度即为 \(\mathcal{O}(n|\Sigma|+L)\)。
/*
Powered by C++11.
Author : Alex_Wei.
*/
#pragma GCC optimize(3)
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ull = unsigned long long;
using pii = pair <int,int>;
#define fi first
#define se second
#define mpi make_pair
#define pb emplace_back
#define mcpy(x,y) memcpy(x,y,sizeof(y))
const int L=2e6+5;
const int N=1e5+5;
const int mod=1e9+7;
void add(ll &x,int y){
x+=y; if(x>=mod)x-=mod;
}
ull hs1[L],hs2[L],p[L];
ull q1(int l,int r){
return hs1[r]-hs1[l-1]*p[r-l+1];
} ull q2(int l,int r){
return hs2[r]-hs2[l-1]*p[r-l+1];
}
int n,q,len,mxlen;
ll f[N][26],pw[N],iv[N],ans[N];
char s[L],t[N];
string qs[N];
vector <pii> qu[L];
int main(){
scanf("%d%d%s%s",&n,&q,s+1,t+1),pw[0]=p[0]=iv[0]=1;
for(int i=1;i<=n;i++)pw[i]=pw[i-1]*2%mod,iv[i]=iv[i-1]*(mod+1>>1)%mod;
for(int i=1;i<L;i++)p[i]=p[i-1]*131;
for(int i=n;i;i--){
for(int j=0;j<26;j++)f[i][j]=f[i+1][j];
add(f[i][t[i]-'a'],pw[n-i]);
} for(int i=1;i<=q;i++){
int id; cin>>id>>qs[i],mxlen=max(mxlen,(int)qs[i].size());
qu[qs[i].size()].pb(mpi(i,id));
} int pre=0,pos=0; len=strlen(s+1);
while(1){
for(int i=1;i<=len;i++)hs1[i]=hs1[i-1]*131+s[i];
for(int l=pre+1;l<=len;l++)for(pii it:qu[l]){
string t=qs[it.fi]; int id=it.fi,k=it.se,slen=t.size();
if(k<pos)continue;
for(int i=1;i<=slen;i++)hs2[i]=hs2[i-1]*131+t[i-1];
ull ap=0,hs=hs2[slen];
for(int i=slen;i<=len;i++)ap+=q1(i-slen+1,i)==hs;
ans[id]=ap*pw[k-pos]%mod;
for(int i=1;i<=slen;i++){
int l=i-1,r=slen-i,it=t[i-1]-'a';
if(q1(len-l+1,len)==q2(1,l)&&q1(1,r)==q2(slen-r+1,slen))
add(ans[id],(f[pos+1][it]-f[k+1][it]+mod)*iv[n-k]%mod);
}
} if(len>=mxlen)break;
for(int i=1;i<=len;i++)s[len+i+1]=s[i];
s[len+1]=t[++pos],pre=len,len=(len<<1)+1;
} for(int i=1;i<=q;i++)cout<<ans[i]<<"\n";
return 0;
}
CF1466G Song of the Sirens的更多相关文章
- Codeforces 1466G - Song of the Sirens(哈希)
Codeforces 题面传送门 & 洛谷题面传送门 事实证明,有的难度评分不算很高.涉及的知识点不算很难的题目也能出得非常神仙 首先考虑如何暴力求答案.注意到一个文本串 \(T\) 在 \( ...
- 读懂UI设计的心理学
好文转载,版权归原作者 作为UI设计师,对待用户就像对待婴儿,知道如何通过界面设计诱导用户非常重要,这就需要了解心理学方面的知识了.今天分享一篇日本设计师的好文,结合心理学与设计,教你读懂心理学,提高 ...
- UVA 590 二十一 Always on the run
Always on the run Time Limit:3000MS Memory Limit:0KB 64bit IO Format:%lld & %llu Submit ...
- python瓦登尔湖词频统计
#瓦登尔湖词频统计: import string path = 'D:/python3/Walden.txt' with open(path,'r',encoding= 'utf-8') as tex ...
- TWELP™ Vocoder
TWELP™ Vocoder DSP Innovations Inc. (DSPINI) announces new class of proprietary vocoders for wide ...
- How to Pronounce the Idiom: ‘Out Like a Light’
How to Pronounce the Idiom: ‘Out Like a Light’ Share Tweet Share Tagged With: Idioms English is full ...
- 哥谭第四季/全集Gotham迅雷下载
<哥谭>(Gotham)第三季刚刚结束,第四季首集的集名就公布了.<Pax Penguina>这个集名在拉丁语中意味着「Pax Romana」,也就是「罗马式的和平」(Roma ...
- Chapter 3 Phenomenon——9
"You were over there," I suddenly remembered, and his chuckle stopped short. “你之前不在这里”我突然记 ...
- [label][转载][web-design-psychology]网页设计心理
原文出处: http://mux.alimama.com/posts/1301 Tip1:信息不要同时全部展示,阶段性地向用户展示当前场景里必要的信息 设计师经常犯的错误:同时将大量信息展示给用户.不 ...
随机推荐
- 【Takin使用日记】记一次TransmittableThreadLocal引起的业务异常
对于常见的 WEB 容器,Takin 通过增强 org.apache.catalina.core.StandardHostValve#invoke 方法,拦截并解析方法入参的 Request 对象中的 ...
- [对对子队]会议记录4.13(Scrum Meeting 4)
今天已完成的工作 梁河览 工作内容:初步完成存档功能 相关issue:实现游戏内UI界面使用的组件 马嘉 工作内容:找到了原料组件 相关issue:实现游戏内UI界面使用的组件 吴昭邦 ...
- 『学了就忘』Linux基础 — 8、虚拟机网络模式说明
目录 1.虚拟机网卡 2.网络连接模式对应工作的网卡 3.桥接模式说明 4.补充说明 这篇主要总结一下虚拟机网络配置中桥接模式.NAT模式和仅主机模式的区别. 打开VMware,选中虚拟机,点击网络适 ...
- 『学了就忘』Linux基础 — 10、VMware虚拟机中克隆的使用
目录 1.什么是克隆 2.克隆的两种类型 (1)完整克隆 (2)链接克隆 3.克隆操作 步骤一:克隆虚拟机 步骤二:进行克隆导向 3.快照与克隆的区别 4.镜像的管理 快照和克隆是VMware中两个非 ...
- Python 模块feedparser安装使用
RSS(简易信息聚合) 简易信息聚合(也叫聚合内容)是一种RSS基于XML标准,在互联网上被广泛采用的内容包装和投递协议.RSS(Really Simple Syndication)是一种描述和同步网 ...
- Python3 TypeError: initial_value must be str or None, not bytes
response.read() returns an instance of bytes while StringIO is an in-memory stream for text only. Us ...
- Arthas在线java进程诊断工具 在线调试神器
tag: java 诊断 堆栈 在线调试 耗时 死锁 arthas 阿里巴巴 Arthas (阿尔萨斯) Arthas 是 Alibaba 开源的Java诊断工具,深受开发者喜爱. 官网文档:http ...
- 【mysql2】下载安装mysql5.7版|不再更新系列
一.下载MySQL 5.7 版 MySQL 5.7 版:官网下载地址 https://dev.mysql.com/downloads/windows/installer/5.7.html 下载的是50 ...
- Linux&c 文件操作,线程进程控制,网络编程,简单知识点梳理
一:文件操作 在linux下,一切皆文件,目录是文件,称为目录文件,内容是该目录的目录项(但是目录只有内核可以编辑,超级用户也不可以编辑),设备也是设备文件,在/dev存放的就是一些设备文件,linu ...
- ansible主机组配置及秘钥分发
ansible主机组配置及秘钥分发 ansible主机组文件位于/etc/ansible/hosts文件中 1 hosts主机经常使用到的变量为: 2 ansible_ssh_host #用于指定被管 ...