https://www.lydsy.com/JudgeOnline/problem.php?id=2434

https://www.luogu.org/problemnew/show/P2414

打字机上只有28个按键,分别印有26个小写英文字母和'B'、'P'两个字母。经阿狸研究发现,这个打字机是这样工作的:

·输入小写字母,打字机的一个凹槽中会加入这个字母(这个字母加在凹槽的最后)。

·按一下印有'B'的按键,打字机凹槽中最后一个字母会消失。

·按一下印有'P'的按键,打字机会在纸上打印出凹槽中现有的所有字母并换行,但凹槽中的字母不会消失。

例如,阿狸输入aPaPBbP,纸上被打印的字符如下:

a aa ab 我们把纸上打印出来的字符串从1开始顺序编号,一直到n。打字机有一个非常有趣的功能,在打字机中暗藏一个带数字的小键盘,在小键盘上输入两个数(x,y)(其中1≤x,y≤n),打字机会显示第x个打印的字符串在第y个打印的字符串中出现了多少次。

阿狸发现了这个功能以后很兴奋,他想写个程序完成同样的功能,你能帮助他么?

因为没有前置技能现学了一发fail树,再回头看就是fail树棵题了。

因为询问x串在y串出现几次,可以直接转化为y串在trie的节点在fail树x串末节点的子树中出现了几次(这个比较绕,但是很好想。)

而且因为这题特殊的建trie的方式,我们完全可以离线,对y排序,然后重新跑一遍建trie的过程,这样就保证了y的快(顺)速(序)查找。

那么中间记录y节点的工作就交给树状数组完成即可。

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cctype>
#include<cstdio>
#include<queue>
#include<cmath>
using namespace std;
typedef long long ll;
const int S=1e5+;
inline int read(){
int X=,w=;char ch=;
while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
while(isdigit(ch))X=(X<<)+(X<<)+(ch^),ch=getchar();
return w?-X:X;
}
struct trie{
int a[],fa,fail;
}tr[S];
struct node{
int to,nxt;
}e[S];
struct data{
int x,y,id;
}p[S];
int m,tot,cnt,ed[S],id,head[S];
int idx,pos[S],a[S],size[S],ans[S];
char s[S];
queue<int>q;
inline bool cmp(data a,data b){
return a.y<b.y;
}
inline void add(int u,int v){
e[++cnt].to=v;e[cnt].nxt=head[u];head[u]=cnt;
}
inline int lowbit(int x){return x&(-x);}
inline void ins(int x,int y){
for(int i=x;i<=idx;i+=lowbit(i))a[i]+=y;
}
inline int qry(int x){
int res=;
for(int i=x;i;i-=lowbit(i))res+=a[i];
return res;
}
void build(){
int n=strlen(s),now=;
for(int i=;i<n;i++){
if(s[i]=='P')ed[++id]=now;
else if(s[i]=='B')now=tr[now].fa;
else{
int c=s[i]-'a';
if(!tr[now].a[c])tr[now].a[c]=++tot;
tr[tr[now].a[c]].fa=now;
now=tr[now].a[c];
}
}
}
void dfs_trie(){
int n=strlen(s),now=,r=,j=,sum=;
for(int i=;i<n;i++){
if(s[i]=='P'){
sum++;
for(;j<=m;j++){
if(p[j].y==sum){
int l=pos[ed[p[j].x]],r=l+size[ed[p[j].x]]-;
ans[p[j].id]=qry(r)-qry(l-);
}else break;
}
}
else if(s[i]=='B'){
ins(pos[now],-);
now=tr[now].fa;
}
else{
now=tr[now].a[s[i]-'a'];
ins(pos[now],);
}
}
}
void getfail(){
tr[].fail=;
for(int i=;i<;i++){
int u=tr[].a[i];
if(u){
tr[u].fail=;
q.push(u);
add(,u);
}
}
while(!q.empty()){
int u=q.front();q.pop();
for(int i=;i<;i++){
if(tr[u].a[i]){
int v=tr[u].a[i];
tr[v].fail=tr[tr[u].fail].a[i];
q.push(v);
add(tr[v].fail,v);
}else tr[u].a[i]=tr[tr[u].fail].a[i];
}
}
return;
}
void dfs_fail(int u){
pos[u]=++idx;size[u]=;
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
dfs_fail(v);
size[u]+=size[v];
}
}
int main(){
scanf("%s",s);
build();getfail();dfs_fail();
m=read();
for(int i=;i<=m;i++){
p[i].x=read(),p[i].y=read(),p[i].id=i;
}
sort(p+,p+m+,cmp);
dfs_trie();
for(int i=;i<=m;i++)printf("%d\n",ans[i]);
return ;
}

+++++++++++++++++++++++++++++++++++++++++++

+本文作者:luyouqi233。               +

+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/ +

+++++++++++++++++++++++++++++++++++++++++++

BZOJ2434:[NOI2011]阿狸的打字机——题解的更多相关文章

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

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

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

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

  3. BZOJ2434:[NOI2011]阿狸的打字机(AC自动机,线段树)

    Description 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母. 经阿狸研究发现,这个打字机是这样工作的 ...

  4. 【AC自动机】【树状数组】【dfs序】洛谷 P2414 [NOI2011]阿狸的打字机 题解

        这一题是对AC自动机的充分理解和树dfs序的巧妙运用. 题目背景 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机. 题目描述 打字机上只有28个按键,分别印有26个小写英文字母和' ...

  5. Bzoj2434 [Noi2011]阿狸的打字机

    Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 2536  Solved: 1415 Description 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到 ...

  6. BZOJ2434 [Noi2011]阿狸的打字机(AC自动机 + fail树 + DFS序 + 线段树)

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

  7. BZOJ2434: [Noi2011]阿狸的打字机(AC自动机 树状数组)

    Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 4140  Solved: 2276[Submit][Status][Discuss] Descript ...

  8. BZOJ2434[Noi2011]阿狸的打字机——AC自动机+dfs序+树状数组

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

  9. BZOJ2434: [Noi2011]阿狸的打字机(fail树+dfs序)

    Description 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母. 经阿狸研究发现,这个打字机是这样工作的 ...

随机推荐

  1. php安全性问题

    目录 常见攻击类型 1.sql注入: 2.xss攻击 3.csrf攻击: php安全三板斧:过滤输入.验证数据,以及转义输出. 1.数据过滤: 2.验证数据: 3.转义输出: laravel 中如何避 ...

  2. 使用nmon监控得出网络实时速度以及最大、最小、平均网络传送速度

    首先我们得搞清楚几个概念,即什么是网速?什么是带宽? 举两个个例子: 1.家里装网线,宽带提供商说我们的带宽是100兆. 2.用迅雷下载电影,迅雷显示实时的下载速度是每秒3兆,或者说是3MB/s. 这 ...

  3. 请求头(request)和响应头(response)

    说一说常见的请求头和相应头都有什么呢? 1)请求(客户端->服务端[request]) GET(请求的方式) /newcoder/hello.html(请求的目标资源) HTTP/1.1(请求采 ...

  4. OSG-基础知识-程序框架

    本文转至http://www.cnblogs.com/shapherd/archive/2010/08/10/osg.html 作者写的比较好,再次收藏,希望更多的人可以看到这个文章 互联网是是一个相 ...

  5. Pycharm中查看方法的源码

    方法1.鼠标放在函数上,Ctrl+B,看源码 方法2.将光标移动至要查看的方法处,按住ctrl 键,点击鼠标左键,即可查看该方法的源码.

  6. Spring 配置请求过滤器,编码格式设为UTF-8,避免中文乱码

    <!-- 配置请求过滤器,编码格式设为UTF-8,避免中文乱码--> <filter> <filter-name>springUtf8Encoding</fi ...

  7. 如何编写 Python 程序

    如何编写 Python 程序 从今以后,保存和运行 Python 程序的标准步骤如下: 对于 PyCharm 用户 打开 PyCharm. 以给定的文件名创建新文件. 输入案例中给出的代码. 右键并运 ...

  8. go通过第三方库 mahonia gbk 转utf8

    go get github.com/axgle/mahonia dec := mahonia.NewDecoder("GBK")ret:=dec.ConvertString(res ...

  9. python 终极篇 cookie与session

    ()cookie与session---------->>>>>>>>>>>>>>>>>>&g ...

  10. java实现遍历一个字符串的每一个字母(总结)

    基础:牢记字符串操作的各种方法: ​​​ ​ String s = "aaaljlfeakdsflkjsadjaefdsafhaasdasd"; // 出现次数 int num = ...