【题解】[NOI2011]阿狸的打字机
\(\text{Solution:}\)
首先观察三种操作:一种是插入一个字符,一种是退回上一步(回到父亲节点)。
所以,我们可以对操作串进行模拟,并处理出每一个串在树上的位置。
接下来,我们考虑如何处理询问。\(y\)是需要跑的串,于是我们应按照\(y\)排序以保证在处理这个\(y\)之前,它本身或者其他的东西没有加进树上过。
考虑同样的模板处理方法:对于一个串出现了几次,我只需要统计这个串结尾编号在\(fail\)树子树中的\(cnt\)个数。
于是自然想到维护子树和的有利武器:\(dfs\)序和树状数组。
于是,我们可以预先处理掉\(dfs\)序,并直接模拟在\(opt\)串上进行的移动操作即可。
这里解释模板的处理思路:首先,既然我们跳到了这个\(fail\)指针,说明我们一定匹配完过当前这整个\(fail\)指针(参考定义)。
观察\(fail\)树上的结构,我们结合上面所述可以知道,所有直接或间接指向\(x\)这个节点的\(fail\)指针,只要跳到了,就一定匹配到过整个串\(x\).
于是,我们可以统计\(fail\)树上\(x\)子树中的\(cnt\),注意每匹配到一个点,应该在\(fail\)树上把从它到根节点的路径上全部加\(1.\)但实际上我们只需要在匹配到的时候对它单点\(+1,\)再\(dfs\)一下\(fail\)树就可以了。
#include<bits/stdc++.h>
using namespace std;
const int MAXN=2000100;
int tot,tr[MAXN],fa[MAXN];
int pos[MAXN],num;
struct Tree{
int ch[26],fail;
}T[MAXN];
vector<int>to[MAXN];
struct Qu{
int x,y,id;
}Q[MAXN];
inline bool cmp(Qu a,Qu b){return a.y<b.y;}
char opt[MAXN];
void Build(char *s,int L){
int u=0;
for(int i=0;i<L;++i){
if(opt[i]=='B')u=fa[u];
else if(opt[i]=='P')pos[++num]=u;
else if(T[u].ch[s[i]-'a'])u=T[u].ch[s[i]-'a'];
else T[u].ch[s[i]-'a']=++tot,fa[tot]=u,u=tot;//介于本题需要有跳回上一步的操作,所以需要记录一下fa
}
//对操作串进行处理,并记录下每一个询问串在树上的位置
}
void bfs(){
queue<int>q;
for(int i=0;i<26;++i){
if(T[0].ch[i]){
int v=T[0].ch[i];
T[v].fail=0;
q.push(v);
}
}
while(!q.empty()){
int u=q.front();q.pop();
for(int i=0;i<26;++i){
if(T[u].ch[i]){
int v=T[u].ch[i];
T[v].fail=T[T[u].fail].ch[i];
q.push(v);
}
else T[u].ch[i]=T[T[u].fail].ch[i];
}
to[T[u].fail].push_back(u);
}
//建立AC自动机并建立fail树
}
int dfn[MAXN],I,ed[MAXN];
void dfs(int u){
dfn[u]=++I;
for(int i=0;i<to[u].size();++i)dfs(to[u][i]);
ed[u]=I;
//处理出每一个树上节点的dfs序列,注意是树上的
}
inline int lowbit(int x){return (x&(-x));}
inline void add(int x,int v){for(;x<=I;x+=lowbit(x))tr[x]+=v;}
inline int query(int x){int res=0;for(;x;x-=lowbit(x))res+=tr[x];return res;}
//树状数组不解释
int ans[MAXN],m;
int main(){
scanf("%s",opt);
int len=strlen(opt);
Build(opt,len);
bfs();dfs(0);
//预处理
scanf("%d",&m);
for(int i=1;i<=m;++i)scanf("%d%d",&Q[i].x,&Q[i].y),Q[i].id=i;
sort(Q+1,Q+m+1,cmp);//按照询问的y从小到大处理
int u=0,r=0,l=0;
for(int i=1;i<=m;++i){
while(r<Q[i].y){
if(opt[l]=='P')r++;//更新目前处理到第几个串
else if(opt[l]=='B'){
add(dfn[u],-1);
u=fa[u];
}//删掉当前u所在字符
else{
u=T[u].ch[opt[l]-'a'];
add(dfn[u],1);
}//更新下一个字符
l++;//操作串后移
}
ans[Q[i].id]=query(ed[pos[Q[i].x]])-query(dfn[pos[Q[i].x]]-1);//注意双映射!
}
for(int i=1;i<=m;++i)printf("%d\n",ans[i]);
return 0;
}
【题解】[NOI2011]阿狸的打字机的更多相关文章
- BZOJ 2434: [Noi2011]阿狸的打字机 [AC自动机 Fail树 树状数组 DFS序]
2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 2545 Solved: 1419[Submit][Sta ...
- [NOI2011]阿狸的打字机(好题!!!!)
2785: [NOI2011]阿狸的打字机 Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 7 Solved: 3[Submit][Status][We ...
- P2414 [NOI2011]阿狸的打字机
P2414 [NOI2011]阿狸的打字机 AC自动机+树状数组 优质题解 <------题目分析 先AC自动机搞出Trie图 然后根据fail指针建一只新树 把树映射(拍扁)到一个序列上,用树 ...
- 【BZOJ2434】[NOI2011]阿狸的打字机 AC自动机+DFS序+树状数组
[BZOJ2434][NOI2011]阿狸的打字机 Description 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P ...
- BZOJ2434: [NOI2011]阿狸的打字机(AC自动机+dfs序+树状数组)
[NOI2011]阿狸的打字机 题目链接:https://www.luogu.org/problemnew/show/P2414 题目背景 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机. ...
- BZOJ 2434: [Noi2011]阿狸的打字机( AC自动机 + DFS序 + 树状数组 )
一个串a在b中出现, 那么a是b的某些前缀的后缀, 所以搞出AC自动机, 按fail反向建树, 然后查询(x, y)就是y的子树中有多少是x的前缀. 离线, 对AC自动机DFS一遍, 用dfs序+树状 ...
- [NOI2011]阿狸的打字机 --- AC自动机 + 树状数组
[NOI2011] 阿狸的打字机 题目描述: 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机. 打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母.经阿狸研究发现, ...
- BZOJ2434 [Noi2011]阿狸的打字机 【AC自动机 + fail树 + 树状数组】
2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec Memory Limit: 256 MB Submit: 3610 Solved: 1960 [Submit][S ...
- bzoj 2434 [Noi2011]阿狸的打字机 AC自动机
[Noi2011]阿狸的打字机 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 4001 Solved: 2198[Submit][Status][D ...
- 洛谷 P2414 [NOI2011]阿狸的打字机 解题报告
P2414 [NOI2011]阿狸的打字机 题目背景 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机. 题目描述 打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母 ...
随机推荐
- VuePress初探(一)
原文参考链接 手把手教你使用 VuePress 搭建个人博客 有阅读障碍的同学,可以跳过第一至四节,下载我写好的工具包: git clone https://github.com/zhangyunch ...
- Unity内生成深度贴图
https://qiita.com/bokkuri_orz/items/08cbaeae6a34fed7f903 https://www.cnblogs.com/sifenkesi/p/4721649 ...
- 使用Json-lib将对象和Json互转
工程下载地址: https://files.cnblogs.com/files/xiandedanteng/jsonSample20200308.rar Depenency: <!-- 使用js ...
- PHP 安装 扩展时 抛出 /usr/local/Cellar/php@7.1/7.1.25/pecl 异常解决
liugx@MacBook-Pro ~/work/php/ext_source/php-xhprof-extension master make installmkdir: /usr/ ...
- MySQL互联网业务使用建议
一.基础规范 表存储引擎必须使用InnoDB 表字符集默认使用utf8,必要时候使用utf8mb4 解读: (1)通用,无乱码风险,汉字3字节,英文1字节 (2)utf8mb4是utf8的超集,有存储 ...
- weekly-contest-205
weekly-contest-205 1 / 5507. 替换所有的问号 class Solution { public String modifyString(String s) { StringB ...
- TP6.0中的密码验证逻辑、验证器的使用
目录 1. 场景一:只有一个密码框,并且是可选项,留空不修改密码,不留空则修改密码 2. 场景二:两个密码框,修改密码时有新密码.确认密码,新密码框不为空时,确认密码才验证 1. 场景一:只有一个密码 ...
- 第1课 - make和makefile
第1课 - make 和 makefile 1. make make 是一个应用程序,位于 /usr/bin/make 目录下,make 有如下的功能: (1)解析源程序之间的依赖关系 (2)根据依赖 ...
- 【深入理解Linux内核架构】3.3 页表
页表:用于建立用户进程空间的虚拟地址空间和系统物理内存(内存.页帧)之间的关联. 向每个进程提供一致的虚拟地址空间. 将虚拟内存页映射到物理内存,因而支持共享内存的实现. 可以在不增加物理内存的情况下 ...
- docker 部署 zabbix
docker部署zabbix 我相信大家都已经会再物理机上跑zabbix并且监控了,那么有没有想过在docker中跑zabbix?下面咱们来看看如何在docker中搭建zabbix并且监控 部署环 ...