BZOJ2434: [Noi2011]阿狸的打字机(fail树+dfs序)
Description
阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机。打字机上只有28个按键,分别印有26个小写英文字母和'B'、'P'两个字母。
经阿狸研究发现,这个打字机是这样工作的:
l 输入小写字母,打字机的一个凹槽中会加入这个字母(这个字母加在凹槽的最后)。
l 按一下印有'B'的按键,打字机凹槽中最后一个字母会消失。
l 按一下印有'P'的按键,打字机会在纸上打印出凹槽中现有的所有字母并换行,但凹槽中的字母不会消失。
例如,阿狸输入aPaPBbP,纸上被打印的字符如下:
a
aa
ab
我们把纸上打印出来的字符串从1开始顺序编号,一直到n。打字机有一个非常有趣的功能,在打字机中暗藏一个带数字的小键盘,在小键盘上输入两个数(x,y)(其中1≤x,y≤n),打字机会显示第x个打印的字符串在第y个打印的字符串中出现了多少次。
阿狸发现了这个功能以后很兴奋,他想写个程序完成同样的功能,你能帮助他么?
Input
输入的第一行包含一个字符串,按阿狸的输入顺序给出所有阿狸输入的字符。
第二行包含一个整数m,表示询问个数。
接下来m行描述所有由小键盘输入的询问。其中第i行包含两个整数x, y,表示第i个询问为(x, y)。
Output
输出m行,其中第i行包含一个整数,表示第i个询问的答案。
Sample Input
3
1 2
1 3
2 3
Sample Output
1
0
解题思路:
长得像不像可持久化数据结构,这道题是可持久化Trie树
然而并没有强制在线a
曾经有个dalao说过:长得像可持久化+不强制在线=离线。
假如说没有问你a串在b串中出现多少次,BZOJ3172fail树裸上。
fail树中子节点个数为出现次数。
先按照打字顺序将trie树、trie图、fail树建好。
trie树要支持回溯(记录父节点)
将询问排序,按y串位置。
我们可以这样认为:
在询问版本中存在的点点权为1,不存在为0
这样统计子树大小时无需重构,更新点权即可。
再遍历原串。
遇到P
更新答案。
遇到其他:
改变一个点的点权。
当然不能暴力更新了。
询问子树权值和和更改单点点值当然要用dfs序了
代码:
#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
const int N=;
struct trnt{
int ch[];
int fl;
int ind;
int oud;
int hd;
int fa;
}tr[N];
struct ent{
int twd;
int lst;
}e[N];
struct qus{
int asp;
int plc;
int no;
int ans;
}q[N];
int lne[N];
char ch[N];
int fin[N];
int len;
int pct;
int siz;
int cnt;
int n,m,dfn;
std::queue<int>Q;
void ade(int f,int t)
{
cnt++;
e[cnt].twd=t;
e[cnt].lst=tr[f].hd;
tr[f].hd=cnt;
}
bool cmp(qus x,qus y)
{
return x.plc<y.plc;
}
bool cmq(qus x,qus y)
{
return x.no<y.no;
}
int lowbit(int x)
{
return x&(-x);
}
void add(int p,int v)
{
while(p<=len&&p)
{
lne[p]+=v;
p+=lowbit(p);
}
return ;
}
int Val(int p)
{
int ans=;
while(p)
{
ans+=lne[p];
p-=lowbit(p);
}
return ans;
}
void dfs(int x)
{
tr[x].ind=++dfn;
for(int i=tr[x].hd;i;i=e[i].lst)
{
int to=e[i].twd;
dfs(to);
}
tr[x].oud=dfn;
return ;
}
void Build()
{
int root=;
len=strlen(ch+);
for(int i=;i<=len;i++)
{
if(ch[i]=='P')
{
fin[++pct]=root;
}else if(ch[i]=='B')
{
root=tr[root].fa;
}else{
int tmp=root;
int c=ch[i]-'a';
if(!tr[root].ch[c])
tr[root].ch[c]=++siz;
root=tr[root].ch[c];
tr[root].fa=tmp;
}
}
root=;
for(int i=;i<;i++)
if(tr[root].ch[i])
Q.push(tr[root].ch[i]);
while(!Q.empty())
{
root=Q.front();
Q.pop();
for(int i=;i<;i++)
{
if(tr[root].ch[i])
{
tr[tr[root].ch[i]].fl=tr[tr[root].fl].ch[i];
Q.push(tr[root].ch[i]);
}else
tr[root].ch[i]=tr[tr[root].fl].ch[i];
}
}
for(int i=;i<=siz;i++)
ade(tr[i].fl,i);
dfs();
return ;
}
void Get_ans()
{
std::sort(q+,q+m+,cmp);
int i=;
int root=;
int num=;
for(int k=;k<=len;k++)
{
if(ch[k]=='P')
{
num++;
while(q[i].plc<num&&i<=m)
i++;
while(q[i].plc==num&&i<=m)
{
int j=fin[q[i].asp];
int h=Val(tr[j].oud);
int o=Val(tr[j].ind-);
q[i].ans=h-o;
i++;
}
}else if(ch[k]=='B')
{
add(tr[root].ind,-);
root=tr[root].fa;
}else{
root=tr[root].ch[ch[k]-'a'];
add(tr[root].ind,);
}
}
std::sort(q+,q+m+,cmq);
return ;
}
int main()
{
scanf("%s",ch+);
scanf("%d",&m);
for(int i=;i<=m;i++)
{
scanf("%d%d",&q[i].asp,&q[i].plc);
q[i].no=i;
}
Build();
Get_ans();
for(int i=;i<=m;i++)
printf("%d\n",q[i].ans);
return ;
}
BZOJ2434: [Noi2011]阿狸的打字机(fail树+dfs序)的更多相关文章
- BZOJ2434[Noi2011]阿狸的打字机——AC自动机+dfs序+树状数组
题目描述 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母. 经阿狸研究发现,这个打字机是这样工作的: l 输入小 ...
- 【BZOJ2434】[NOI2011]阿狸的打字机 AC自动机+DFS序+树状数组
[BZOJ2434][NOI2011]阿狸的打字机 Description 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P ...
- BZOJ 2434: [Noi2011]阿狸的打字机( AC自动机 + DFS序 + 树状数组 )
一个串a在b中出现, 那么a是b的某些前缀的后缀, 所以搞出AC自动机, 按fail反向建树, 然后查询(x, y)就是y的子树中有多少是x的前缀. 离线, 对AC自动机DFS一遍, 用dfs序+树状 ...
- BZOJ2434 [NOI2011] 阿狸的打字机 【树链剖分】【线段树】【fail树】【AC自动机】
题目分析: 画一下fail树,就会发现就是x的子树中属于y路径的,把y剖分一下,用线段树处理 $O(n*log^2 n)$. 代码: #include<bits/stdc++.h> usi ...
- 【BZOJ 2434】 [Noi2011]阿狸的打字机 fail树+树状数组
就是考了一个fail树的神奇应用我们建出fail树之后,发现我们就是在求y到根的路径上所有的点在以x为根的子树里的个数,这个我们离线后用树状数组+dfs序即可解决 #include <cstdi ...
- NOI 2011 阿狸的打字机 (AC自动机+dfs序+树状数组)
题目大意:略(太长了不好描述) 良心LOJ传送门 先对所有被打印的字符串建一颗Trie树 观察数据范围,并不能每次打印都从头到尾暴力建树,而是每遍历到一个字符就在Trie上插入这个字符,然后记录每次打 ...
- BZOJ2434 [Noi2011]阿狸的打字机 【AC自动机 + fail树 + 树状数组】
2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec Memory Limit: 256 MB Submit: 3610 Solved: 1960 [Submit][S ...
- [NOI2011][bzoj2434] 阿狸的打字机 [AC自动机+dfs序+fail树+树状数组]
题面 传送门 正文 最暴力的 最暴力的方法:把所有询问代表的字符串跑一遍kmp然后输出 稍微优化一下:把所有询问保存起来,把模板串相同的合并,求出next然后匹配 但是这两种方法本质没有区别,都是暴力 ...
- 【BZOJ-2434】阿狸的打字机 AC自动机 + Fail树 + DFS序 + 树状数组
2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 2022 Solved: 1158[Submit][Sta ...
- BZOJ2434: [NOI2011]阿狸的打字机(AC自动机+dfs序+树状数组)
[NOI2011]阿狸的打字机 题目链接:https://www.luogu.org/problemnew/show/P2414 题目背景 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机. ...
随机推荐
- Android旋转屏幕后国际化语言失效的解决的方法
本文已同步至个人博客:liyuyu.cn 近期在项目中使用到了国际化多语言(英文+中文),但在使用时发现了一个问题.当屏幕旋转后.APP语言(中文)自己主动转换为了系统语言(英文).设置了Activi ...
- [LeetCode]Single Number 异或的妙用
1.数组中仅仅有一个元素仅仅出现一次,其余出现偶数次. 利用异或中同样元素相互抵消的方式求解. 2.数组中仅仅有2个元素仅仅出现一次.其余出现偶数次. class Solution { public: ...
- Beta分布从入门到精通
近期一直有点小忙,可是不知道在瞎忙什么,最终有时间把Beta分布的整理弄完. 以下的内容.夹杂着英文和中文,呵呵- Beta Distribution Beta Distribution Defini ...
- 优化数据页面(20)——1:n的数据关系
设计要点:优化数据页面.界面设计.美化exce 阿金:那一对多的关系-- 秀秀:不是:n结构么? 阿金:嗯,这俺知道.俺特别喜欢这样的格式,那样显得非常上档次! 秀秀:俺也喜欢. 由于页面上有空白,认 ...
- 第六课 Struts的视图组件
Struts框架的视图负责为客户提供动态网页内容. Struts的视图主要由JSP网页构成.此外还包含客户化的标签和ActionForm Bean.这些组件提供了 对国际化.接收用户输入的表单数据.表 ...
- hdoj--2955--Robberies(背包好题)
Robberies Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total ...
- 在使用Easy Sysprep 封装系统时要注意的地方
安装好常用软件后要作的工作: 1.软件安装到D盘 QQ/ QQ管家 / Chrome / 压缩软件 C盘 office2010 / sogou /foxit ...
- Dcloud+mui 压缩上传图片到服务器
chooseImgFromAlbums选择图片 chooseImgFromPictures 拍照 changeToLocalUrl 转换成可用的路径 uploadpic.compressImg 压缩图 ...
- [Python] Read and Parse Files in Python
This lesson will teach you how to read the contents of an external file from Python. You will also l ...
- java之 ------ 几种常见的简单设计模式
前言: 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.用于解决特定环境下.反复出现的特定问题的解决方式.使用设计模式是为了可重用代码.让代 ...