AC自动机:BZOJ 2434 阿狸的打字机
2434: [Noi2011]阿狸的打字机
Time Limit: 10 Sec Memory Limit: 256 MB
Submit: 1834 Solved: 1053
[Submit][Status][Discuss]
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
HINT
1<=N<=10^5
1<=M<=10^5
输入总长<=10^5
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
const int maxn=1e5+;
char S[maxn];
int Query[maxn][],ans[maxn],cntQ;
struct A_Cautomation{
int ch[maxn][],fail[maxn],end[maxn],fa[maxn],ID[maxn],cnt,root,cont;
int fir[maxn],nxt[maxn],to[maxn],cot;
int be[maxn],en[maxn],sjc;
void Init()
{
memset(ch,,sizeof(ch));
memset(fail,,sizeof(fail));
memset(end,,sizeof(end));
sjc=cot=cnt=cont=root=;
}
void Insert()
{
scanf("%s",S);
int len=strlen(S),node=root;
for(int i=;i<len;i++)
{
if(S[i]>='a'&&S[i]<='z'){
if(ch[node][S[i]-'`']){
node=ch[node][S[i]-'`'];
}
else{
fa[++cnt]=node;
node=ch[node][S[i]-'`']=cnt;
}
}
else{
if(S[i]=='B'){
node=fa[node];
}
else{
end[node]=++cont;
ID[cont]=node;
}
}
}
}
void Build()
{
queue<int>q;
for(int i=;i<=;i++){
if(ch[root][i]){
fail[ch[root][i]]=root;
q.push(ch[root][i]);
}
else
ch[root][i]=root;
}
while(!q.empty())
{
int node=q.front();q.pop();
for(int i=;i<=;i++){
if(ch[node][i]){
fail[ch[node][i]]=ch[fail[node]][i];
q.push(ch[node][i]);
}
else{
ch[node][i]=ch[fail[node]][i];
}
}
}
} void addedge(int a,int b)
{nxt[++cot]=fir[a];fir[a]=cot;to[cot]=b;} void DFS(int node)
{
be[node]=++sjc;
for(int i=fir[node];i;i=nxt[i])
DFS(to[i]);
en[node]=sjc;
} void BuildTree()
{
for(int i=;i<=cnt;i++)
addedge(fail[i],i); DFS(root);
} int bit[maxn];
void change(int k,int x)
{
while(k<=)
{
bit[k]+=x;
k+=k&(-k);
}
} int Quer(int k)
{
int ret=;
while(k)
{
ret+=bit[k];
k-=k&(-k);
}
return ret;
} void Solve()
{
memset(fir,,sizeof(fir));cot=;
memset(bit,,sizeof(bit));
for(int i=;i<=cntQ;i++)
Query[i][]=ID[Query[i][]],
Query[i][]=ID[Query[i][]],
addedge(Query[i][],Query[i][]); int len=strlen(S),node=root;
for(int i=;i<len;i++)
{
if(S[i]>='a'&&S[i]<='z'){
node=ch[node][S[i]-'`'];
change(be[node],);
}
else{
if(S[i]=='B'){
change(be[node],-);
node=fa[node];
}
else{
for(int i=fir[node];i;i=nxt[i]){
ans[i]=Quer(en[to[i]])-Quer(be[to[i]]-);
}
}
}
} for(int i=;i<=cntQ;i++)
printf("%d\n",ans[i]);
}
}AC; int main()
{
AC.Init();
AC.Insert();
AC.Build();
AC.BuildTree(); int Q;
scanf("%d",&Q);
while(Q--)
scanf("%d%d",&Query[cntQ][],&Query[++cntQ][]); AC.Solve();
return ;
}
AC自动机:BZOJ 2434 阿狸的打字机的更多相关文章
- BZOJ 2434 阿狸的打字机(ac自动机+dfs序+树状数组)
题意 给你一些串,还有一些询问 问你第x个串在第y个串中出现了多少次 思路 对这些串建ac自动机 根据fail树的性质:若x节点是trie中root到t任意一个节点的fail树的祖先,那么x一定是y的 ...
- BZOJ 2434 阿狸的打字机
http://www.lydsy.com/JudgeOnline/problem.php?id=2434 思路:建立fail树,并找出dfs序,那剩下要做的就是每次找到一个串的位置,然后询问它的区间里 ...
- [NOI 2011][BZOJ 2434] 阿狸的打字机
传送门 AC自动机 + 树状数组 建成AC自动机后,设end[i]为第i个串的末尾在Trie树上的节点. 可以发现,对于一个询问(x,y),ans等于Trie树上root到end[y]这条链上fail ...
- BZOJ 2434 阿狸的打字机 | AC自动机
题目戳这里 AC自动机上有神奇的东西叫做fail指针--所有fail指针连起来恰好构成一棵以1为根的树! 而这道题问x在y中出现过多少次,就是问Trie树上根到y的结束节点的路径上有多少节点能通过跳f ...
- bzoj 2434 阿狸的打字机 - Aho-Corasick自动机 - 树状数组
题目传送门 传送站I 传送站II 题目大意 阿狸有一个打字机,它有3种键: 向缓冲区追加小写字母 P:打印当前缓冲区(缓冲区不变) B:删除缓冲区中最后一个字符 然后多次询问第$x$个被打印出来的串在 ...
- BZOJ 2434 阿狸的打字机(fail树)
题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2434 题意:阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28 ...
- bzoj 2434: 阿狸的打字机 fail树+离线树状数组
题目大意: http://www.lydsy.com/JudgeOnline/problem.php?id=2434 题解: 首先我们可以发现这个打字的过程本身就是在Trie上滚来滚去的过程 所以我们 ...
- bzoj 2434 阿狸的打字机 fail树的性质
如果a串是另b串的后缀,那么在trie图上沿着b的fail指针走一定可以走到a串. 而a串在b串里出现多少次就是它是多少个前缀的后缀. 所以把fail边反向建树维护个dfs序就行了. 并不是很难... ...
- AC自动机-算法详解
What's Aho-Corasick automaton? 一种多模式串匹配算法,该算法在1975年产生于贝尔实验室,是著名的多模式匹配算法之一. 简单的说,KMP用来在一篇文章中匹配一个模式串:但 ...
随机推荐
- windows下jboss启动、配置、访问
window 下的jboss启动.配置.访问 1.进入jboss\server\default\deploy\jboss-web.deployer 执行run命令 2.jboss访问地址:http:/ ...
- linux下面安装和配置nginx
下载nginx-1.0.2.tar.gz wget nginx-1.0.2.tar.gz 解压 nginx-1.0.2.tar.gz tar -xzvf nginx-1.0.2.tar.gz 配置安装 ...
- typeerror $.ajax is not a function
在web开发中使用jQuery进行前端开发遇到这么个问题,纠结了很久终于解决了,下面说一下解决方法. 大家可以参照下面几种排查的方法. 1.首先检查是否引用jQuery的库. 2.页面如果使用的ifr ...
- TFS 安装与管理
整了几天TFS,把相关的一些配置与安装的要点简单记下,希望对大家有用.本篇主要是安装与配置上的内容,下一篇会介绍如何使用以及使用方面的相关心得体会. 本篇内容简要: 1. 安装部署 1.1. 流 ...
- HTML5+移动APP(2)
原理: html 页面负责内容: ui 负责页面样式: js 负责调用原生app方法. html5: html5这部分负责页面,也就是app中你看到的东西,大概的架构和内容 ui: mui 介绍:和H ...
- 解决vim不能使用方向键和退格键问题
1.使用vi命令时,不能正常编辑文件,使用方向键时老是出现很多字母,或者退格键却变成方向键的功能 只要重装一下vi的依赖包即可完美解决vi编辑器方向键变字母的问题.rpm -e vim-enhance ...
- IOS开发网络篇之──ASIHTTPRequest详解
目录 目录 发起一个同步请求 创建一个异步请求 队列请求 请求队列上下文 ASINetworkQueues, 它的delegate提供更为丰富的功能 取消异步请求 安全的内存回收建议 向服务器端上传数 ...
- JavaScript 保留关键字
JavaScript 保留关键字 在 JavaScript 中,一些标识符是保留关键字,不能用作变量名或函数名. JavaScript 标准 所有的现代浏览器完全支持 ECMAScript 3(ES3 ...
- php文件粘贴上传
<?php header("Access-Control-Allow-Origin:*"); $url = 'http://'.$_SERVER['HTTP_HOST']; ...
- POJ 1734.Sightseeing trip (Floyd 最小环)
Floyd 最小环模板题 code /* floyd最小环,记录路径,时间复杂度O(n^3) 不能处理负环 */ #include <iostream> #include <cstr ...