阿狸的打字机

\(\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]阿狸的打字机的更多相关文章

  1. BZOJ 2434: [Noi2011]阿狸的打字机 [AC自动机 Fail树 树状数组 DFS序]

    2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 2545  Solved: 1419[Submit][Sta ...

  2. [NOI2011]阿狸的打字机(好题!!!!)

    2785: [NOI2011]阿狸的打字机 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 7  Solved: 3[Submit][Status][We ...

  3. P2414 [NOI2011]阿狸的打字机

    P2414 [NOI2011]阿狸的打字机 AC自动机+树状数组 优质题解 <------题目分析 先AC自动机搞出Trie图 然后根据fail指针建一只新树 把树映射(拍扁)到一个序列上,用树 ...

  4. 【BZOJ2434】[NOI2011]阿狸的打字机 AC自动机+DFS序+树状数组

    [BZOJ2434][NOI2011]阿狸的打字机 Description 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P ...

  5. BZOJ2434: [NOI2011]阿狸的打字机(AC自动机+dfs序+树状数组)

    [NOI2011]阿狸的打字机 题目链接:https://www.luogu.org/problemnew/show/P2414 题目背景 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机. ...

  6. BZOJ 2434: [Noi2011]阿狸的打字机( AC自动机 + DFS序 + 树状数组 )

    一个串a在b中出现, 那么a是b的某些前缀的后缀, 所以搞出AC自动机, 按fail反向建树, 然后查询(x, y)就是y的子树中有多少是x的前缀. 离线, 对AC自动机DFS一遍, 用dfs序+树状 ...

  7. [NOI2011]阿狸的打字机 --- AC自动机 + 树状数组

    [NOI2011] 阿狸的打字机 题目描述: 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机. 打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母.经阿狸研究发现, ...

  8. BZOJ2434 [Noi2011]阿狸的打字机 【AC自动机 + fail树 + 树状数组】

    2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec  Memory Limit: 256 MB Submit: 3610  Solved: 1960 [Submit][S ...

  9. bzoj 2434 [Noi2011]阿狸的打字机 AC自动机

    [Noi2011]阿狸的打字机 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 4001  Solved: 2198[Submit][Status][D ...

  10. 洛谷 P2414 [NOI2011]阿狸的打字机 解题报告

    P2414 [NOI2011]阿狸的打字机 题目背景 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机. 题目描述 打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母 ...

随机推荐

  1. 备份etc下的内容

    echo "start backup..."sleep 3cp -av /etc/ /data/etc`date +%F`/echo "end backup"~ ...

  2. 尝试MatCap类型shader

    听说MatCap能在低端机上做出很漂亮的pbr效果,就尝试了一下. MatCap全称MaterailCapture,里面存的是光照信息,通过法线的xy分量去采样matcap,得到在该方向法线的光照信息 ...

  3. 听过N次还是不会之:浏览器输入url后到底经历了什么

    有没有这种场景:当你被问起某一项知识点时,你大脑里想起经常看到过这样的问题,可是具体是怎么样就是说不清楚. 好吧,我就是这样的,于是整理一下,实在记不住,以后找起来也方便. 当你在浏览器地址栏里输入一 ...

  4. CA定义以及功能说明

    当您访问以HTTPS开头的网站时,即表示正在使用CA.CA是Internet的重要组成部分.如果不存在CA,那么将无法安全在线购物以及使用网银在线业务等.什么是CA?CA具体是做什么的,又是如何确保您 ...

  5. 2019HNCPC C Distinct Substrings 后缀自动机

    题意 给定一个长度为n字符串,字符集大小为m(1<=n,m<=1e6),求\(\bigoplus_{c = 1}^{m}\left(h(c) \cdot 3^c \bmod (10^9+7 ...

  6. php反序列化总结与学习

    基础知识: 1.php类与对象 2.魔术函数 3.序列化方法 类与对象 <?php class test{ public $var = "hello world"; publ ...

  7. 关于ASP.NET MVC的权限认证的一些总结

    最近在学ASP.NET MVC的权限认证的一些东西,上网搜索了一阵,发现网上的方法大多数是以下几类: 一.FormsAuthentication.SetAuthCookie(admin.Name, f ...

  8. Zabbix icmp pinger processes more than 75% busy

    Zabbix icmp pinger processes more than 75% busy   Zabbix server报"Zabbix icmp pinger processes m ...

  9. VMware参数disk.EnableUUID生效扫描不出来UUID

    问题描述:搭建RAC中的共享磁盘,在一个节点上部署磁盘,另一个节点加入共享磁盘,使用扫描UUID的方法,但是莫名其妙一直扫描不出来UUID,使用了各种各样的方法,一个星期时间接近崩溃,又搞了一下午的测 ...

  10. python文件的相关操作

    python 目录 python 1.python文件的介绍 使用文件的目的 Python文件的类型主要有两种:文本文件和二进制文件. 操作文件的流程主要有三步:打开-操作-关闭操作. 2.文件的打开 ...