BZOJ 2434 [Noi2011]阿狸的打字机(AC自动机)
【题目链接】 http://www.lydsy.com/JudgeOnline/problem.php?id=2434
【题目大意】
给出一个打印的过程,'a'-'z'表示输入字母,P表示打印该字符串
B表示删去一个字符。问第x个打印的字符串在第y个打印的字符串中出现的次数
【题解】
我们根据打印的过程建立trie树,
当x是y的子串当且仅当y到根的链上有fail指针指向x的结尾,
而x在y中的出现次数则取决于有几个这样的指针,
我们根据fail指针建立fail树,按照fail树的dfs序进行统计,
在每个y处记录其要查询的x,在y点用树状数组对x点求dfs序区间和即可。
【代码】
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
using namespace std;
const int N=100010;
int dfn,l[N],r[N],ans[N];
vector<int> v[N],Q[N],ID[N];
namespace BIT{
int c[N<<1]; //dfs
void Initialize(){memset(c,0,sizeof(c));}
void add(int x,int v){while(x<=dfn)c[x]+=v,x+=x&-x;}
int query(int x){int res=0;while(x)res+=c[x],x-=x&-x;return res;}
}
namespace AC_DFA{
const int Csize=26;
int id,tot,son[N][Csize],sum[N],f[N],fail[N],q[N],pos[N],match[N];
void Initialize(){
memset(sum,0,sizeof(int)*(tot+1));
memset(fail,0,sizeof(int)*(tot+1));
for(int i=0;i<=tot;i++)for(int j=0;j<Csize;j++)son[i][j]=0;
tot=0; id=0; fail[0]=-1;
}
inline int Tr(char ch){return ch-'a';}
void Build(char *s){
int x=0;
for(int l=strlen(s),i=0,w;i<l;i++){
if(s[i]=='P')pos[++id]=x;
else if(s[i]=='B')x=f[x];
else{
if(!son[x][w=Tr(s[i])]){
son[x][w]=++tot;
f[tot]=x;
}x=son[x][w];
}
}
}
void MakeFail(){
int h=1,t=0,i,j,x=0;
for(i=0;i<Csize;i++)if(son[0][i])q[++t]=son[0][i];
while(h<=t)for(x=q[h++],i=0;i<Csize;i++)
if(son[x][i]){
fail[son[x][i]]=son[fail[x]][i],q[++t]=son[x][i];
}else son[x][i]=son[fail[x]][i];
}
void Solve(char *s){
using namespace BIT;
BIT::Initialize();
int x=0,id=0;
add(l[0],1);
for(int L=strlen(s),i=0;i<L;i++){
if(s[i]=='P'){
id++;
for(int k=0;k<Q[id].size();k++){
int u=pos[Q[id][k]];
ans[ID[id][k]]=query(r[u])-query(l[u]-1);
}
}else if(s[i]=='B')add(l[x],-1),x=f[x];
else x=son[x][Tr(s[i])],add(l[x],1);
}
}
}
void Dfs(int x){
l[x]=++dfn;
for(int i=0;i<v[x].size();i++)Dfs(v[x][i]);
r[x]=++dfn;
}
char s[N];
int main(){
using namespace AC_DFA;
Initialize();
scanf("%s",s);
Build(s); MakeFail();
for(int i=1;i<=tot;i++)v[fail[i]].push_back(i);
int m,x,y;
scanf("%d",&m);
for(int i=1;i<=m;i++){
scanf("%d%d",&x,&y);
Q[y].push_back(x);
ID[y].push_back(i);
}Dfs(0); Solve(s);
for(int i=1;i<=m;i++)printf("%d\n",ans[i]);
return 0;
}
BZOJ 2434 [Noi2011]阿狸的打字机(AC自动机)的更多相关文章
- BZOJ 2434: [Noi2011]阿狸的打字机 [AC自动机 Fail树 树状数组 DFS序]
2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 2545 Solved: 1419[Submit][Sta ...
- BZOJ 2434: [Noi2011]阿狸的打字机( AC自动机 + DFS序 + 树状数组 )
一个串a在b中出现, 那么a是b的某些前缀的后缀, 所以搞出AC自动机, 按fail反向建树, 然后查询(x, y)就是y的子树中有多少是x的前缀. 离线, 对AC自动机DFS一遍, 用dfs序+树状 ...
- bzoj 2434 [Noi2011]阿狸的打字机 AC自动机
[Noi2011]阿狸的打字机 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 4001 Solved: 2198[Submit][Status][D ...
- bzoj 2434 [Noi2011]阿狸的打字机——AC自动机
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2434 dfs AC自动机,走过的点权值+1,回溯的时候权值-1:走到询问的 y 串的节点,看 ...
- BZOJ 2434: [Noi2011]阿狸的打字机 AC自动机+fail树+线段树
Description 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母. 经阿狸研究发现,这个打字机是这样工作的 ...
- BZOJ.2434.[NOI2011]阿狸的打字机(AC自动机 树状数组 DFS序)
题目链接 首先不需要存储每个字符串,可以将所有输入的字符依次存进Trie树,对于每个'P',记录该串结束的位置在哪,以及当前节点对应的是第几个串(当前串即根节点到当前节点):对于'B',只需向上跳一个 ...
- 【BZOJ】2434: [Noi2011]阿狸的打字机 AC自动机+树状数组+DFS序
[题意]阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母. 经阿狸研究发现,这个打字机是这样工作的: l 输入小写 ...
- 【BZOJ2434】[NOI2011]阿狸的打字机 AC自动机+DFS序+树状数组
[BZOJ2434][NOI2011]阿狸的打字机 Description 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P ...
- [NOI2011]阿狸的打字机 --- AC自动机 + 树状数组
[NOI2011] 阿狸的打字机 题目描述: 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机. 打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母.经阿狸研究发现, ...
- 【刷题】BZOJ 2434 [Noi2011]阿狸的打字机
Description 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母. 经阿狸研究发现,这个打字机是这样工作的 ...
随机推荐
- jQuery.pin.js笔记
jQuery.pin.js是一个把元素钉在页面上某个位置的插件,它能够将某个元素一直挂在一个固定的位置而不论滚动条是否滚动. 特点: 1. 可以钉住一个元素,主要作用就是滚动超出的时候不会隐藏而是一直 ...
- Tinyos Makerules解读
Makerules 文件解读 位于/opt/tinyos-2.1.2/support/make #-*-Makefile-*- vim:syntax=make #$Id: Makerules,v 1. ...
- 【shell】shell编程(五)-读取参数
通过前几篇文章的学习,我们学会了shell的基本语法.在linux的实际操作中,我们经常看到命令会有很多参数,例如:ls -al 等等,那么这个参数是怎么处理的呢? 接下来我们就来看看shell脚本对 ...
- Android中的通信Volley
1. Volley简介 我们平时在开发Android应用的时候不可避免地都需要用到网络技术,而多数情况下应用程序都会使用HTTP协议来发送和接收网络数据.Android系统中主要提供了两种方式来进行H ...
- Thinkphp的自定义路由(route.php)
废话:因为thinkphp的默认路由会导致URL特别长,从而会影响搜索引擎优化.所以就衍生了自定义路由,尽量将URL缩短. 这是默认的路由文件: <?php return [ '__patter ...
- SQLite3 安装、基本操作
1. 安装SQLite3 sudo apt-get install sqlite3 2. 安装Sqlite3编译需要的工具包 如果,你需要的话可以安装该工具包.只是为了体验一把,可以不安装.该项是可选 ...
- http状态码说明
在学习网页设计的时候都应该知道状态码,但我们常见的状态码都是200,404,下面介绍其他的状态值 1开头的http状态码表示临时响应并需要请求者继续执行操作的状态代码. 100 (继续) 请求者应 ...
- C++中stringstream样例
包含头文件 #include <sstream> 初始化可以使用 clear(). str( ) 赋值: 这里的clear方法,实际上是清空stringstream的状态(比如出错等),清 ...
- ftp--pureftpd1.0.46
pureftpd的新版本1.0.46安装过程与之前的相同 但是之后的配置,有些许不同 pureftpd安装过程: # cd /usr/local/src # wget # cd pure-1.0.46 ...
- 一致性hash理解
在做memcached分布式集群时往往要用到一致性hash算法来调节缓存数据的分布. 通常的hash算法是以服务器数量N作为模数,使用key%N的值来获得最终位置,显然当服务器数量发生变化即N发生变化 ...