[BZOJ2434][Noi2011]阿狸的打字机 AC自动机+树状数组+离线
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2434
题目中这种多个串匹配的问题,一下子就想到了AC自动机。然后发现如果要建立AC自动机,跟着题目中的方式,不用把每个串提出来。如果是一个普通字符就直接加进去,如果是P就把当前节点记录下来,代表一个串,如果是B就相当于退回到trie树中的父亲节点。
建好AC自动机后来观察一下题目中的问题。这个询问相当于统计从根节点到代表y串的那个节点上的路径上,有多少个节点可以通过跳fail指针的方式到达x串的节点。
暴力统计显然是不行的,观察到fail路径上的每一个点的出度都为1,那么将fail全部反过来就是一棵树。问题就变成了在x的子树中,有多少个从根节点到y串的节点的路径上的节点。把fail树的dfs序求出来,我们可以用树状数组求子树和。
考虑离线。那么重新模拟题目中打字的过程,如果加入了一个字符,对应树状数组中此节点dfs序的位置+1,如果被删除了,则-1。这样就能实时维护树状数组中的点全部是y串中的点,于是提前处理一下,如果有关于y串的询问,答案就是x串的子树和,也就是dfs序对应的区间和。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int inline readint(){
int Num;char ch;
while((ch=getchar())<''||ch>'');Num=ch-'';
while((ch=getchar())>=''&&ch<='') Num=Num*+ch-'';
return Num;
}
void outint(int x){
if(x>=) outint(x/);
putchar(x%+'');
}
char s[];
int Len,M;
int ch[][],fa[],sz=;
int pos[],tot=;
void Build_trie(){
int now=;
for(int i=;i<=Len;i++){
if(s[i]>='a'&&s[i]<='z'){
int idx=s[i]-'a';
if(!ch[now][idx]) ch[now][idx]=++sz;
fa[ch[now][idx]]=now;
now=ch[now][idx];
}
else if(s[i]=='B') now=fa[now];
else pos[++tot]=now;
}
}
int to[],ne[],fir[],cnt=;
void Addedge(int a,int b){
to[++cnt]=b;
ne[cnt]=fir[a];
fir[a]=cnt;
}
int fail[],q[];
void Set_fail(){
memset(fir,-,sizeof(fir));
int head=,tail=;
q[]=;
while(head<=tail){
int now=q[head];
for(int i=;i<;i++){
if(ch[now][i]){
q[++tail]=ch[now][i];
int tmp=now?ch[fail[now]][i]:;
fail[ch[now][i]]=tmp;
Addedge(tmp,ch[now][i]);
}
else ch[now][i]=ch[fail[now]][i];
}
head++;
}
}
int dfn=,in[],out[];
void Dfs(int x){
in[x]=++dfn;
for(int i=fir[x];i!=-;i=ne[i]) Dfs(to[i]);
out[x]=dfn;
}
struct Query{
int x,y,idx;
bool operator < (const Query &_)const{
return y<_.y;
}
}qry[];
int tree[];
int inline lowbit(int &x){
return x&-x;
}
void Add(int x,int d){
while(x<=dfn){
tree[x]+=d;
x+=lowbit(x);
}
}
int Sum(int x){
int sum=;
while(x){
sum+=tree[x];
x-=lowbit(x);
}
return sum;
}
int Ans[];
int main(){
scanf("%s",s+);
Len=strlen(s+);
Build_trie();
Set_fail();
Dfs();
M=readint();
for(int i=;i<=M;i++){
qry[i].x=readint();
qry[i].y=readint();
qry[i].idx=i;
}
sort(qry+,qry++M);
int now=,sk=,qk=;
for(int i=;i<=Len;i++){
if(s[i]>='a'&&s[i]<='z'){
now=ch[now][s[i]-'a'];
Add(in[now],);
}
else if(s[i]=='B'){
Add(in[now],-);
now=fa[now];
}
else{
sk++;
while(qry[qk].y==sk){
Ans[qry[qk].idx]=Sum(out[pos[qry[qk].x]])-Sum(in[pos[qry[qk].x]]-);
qk++;
}
}
}
for(int i=;i<=M;i++){
outint(Ans[i]);
putchar('\n');
}
return ;
}
[BZOJ2434][Noi2011]阿狸的打字机 AC自动机+树状数组+离线的更多相关文章
- BZOJ2434: [Noi2011]阿狸的打字机(AC自动机 树状数组)
Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 4140 Solved: 2276[Submit][Status][Discuss] Descript ...
- 【BZOJ】2434: [Noi2011]阿狸的打字机 AC自动机+树状数组+DFS序
[题意]阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母. 经阿狸研究发现,这个打字机是这样工作的: l 输入小写 ...
- [NOI2011]阿狸的打字机 --- AC自动机 + 树状数组
[NOI2011] 阿狸的打字机 题目描述: 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机. 打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母.经阿狸研究发现, ...
- BZOJ.2434.[NOI2011]阿狸的打字机(AC自动机 树状数组 DFS序)
题目链接 首先不需要存储每个字符串,可以将所有输入的字符依次存进Trie树,对于每个'P',记录该串结束的位置在哪,以及当前节点对应的是第几个串(当前串即根节点到当前节点):对于'B',只需向上跳一个 ...
- BZOJ2434[Noi2011]阿狸的打字机——AC自动机+dfs序+树状数组
题目描述 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母. 经阿狸研究发现,这个打字机是这样工作的: l 输入小 ...
- BZOJ2434:[NOI2011]阿狸的打字机(AC自动机,线段树)
Description 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母. 经阿狸研究发现,这个打字机是这样工作的 ...
- bzoj 2434 阿狸的打字机 - Aho-Corasick自动机 - 树状数组
题目传送门 传送站I 传送站II 题目大意 阿狸有一个打字机,它有3种键: 向缓冲区追加小写字母 P:打印当前缓冲区(缓冲区不变) B:删除缓冲区中最后一个字符 然后多次询问第$x$个被打印出来的串在 ...
- 洛谷P2414 阿狸的打字机 [NOI2011] AC自动机+树状数组/线段树
正解:AC自动机+树状数组/线段树 解题报告: 传送门! 这道题,首先想到暴力思路还是不难的,首先看到y有那么多个,菜鸡如我还不怎么会可持久化之类的,那就直接排个序什么的然后按顺序做就好,这样听说有7 ...
- 【BZOJ2434】[NOI2011]阿狸的打字机 AC自动机+DFS序+树状数组
[BZOJ2434][NOI2011]阿狸的打字机 Description 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P ...
随机推荐
- python 基础之第十天(闭包,装饰器,生成器,tarfile与hashlib模块使用)
局部变量与全局变量 局部变量:在函数里面定义的,只有当函数活动时才生效 全局变量:不在函数里面的 In [1]: x=10 In [2]: def bar(): ...: x=20 ...: prin ...
- BZOJ_3729_Gty的游戏_博弈论+splay+dfs序
BZOJ_3729_Gty的游戏_博弈论+splay+dfs序 Description 某一天gty在与他的妹子玩游戏. 妹子提出一个游戏,给定一棵有根树,每个节点有一些石子,每次可以将不多于L的石子 ...
- 怎样编写高质量的 Java 代码
代码质量概述 怎样辨别一个项目代码写得好还是坏?优秀的代码和腐化的代码区别在哪里?怎么让自己写的代码既漂亮又有生命力?接下来将对代码质量的问题进行一些粗略的介绍.也请有过代码质量相关经验的朋友提出宝贵 ...
- Firebug的安装与使用
第一步,点击 Firefox 浏览器上的“工具”选项,然后点击“附加软件”,在弹出的小窗口中,点击右下角的“获取扩展”选项,如图 4 所示. 图 4. 获取扩展 第二步,在点击“获取扩展”选项后,打开 ...
- Asset Catalog Help (八)---Customizing Image Sets for Devices
Customizing Image Sets for Devices Add images to a set that are customized for display on the device ...
- Flutter实战视频-移动电商-02.Flutter实战建立项目和编写入口文件
02.Flutter实战建立项目和编写入口文件 创建项目: flutter create flutter_shop 创建完成之后呢,它会提示我们, 进入flutter_shop的目录,然后执行flut ...
- python-os.walk()使用举例
文件目录结构 dir 1 1 1.txt 2.txt 3.txt 2 2.txt 3 4 4.txt 3.txt 1.txt 2 2.txt 3 3.txt dir.txt 代码: import os ...
- 洛谷 - P3164 - 和谐矩阵 - 高斯约旦消元法
为什么可以跑n立方,我也不知道,反正就是可以. 模2意义的,据说每一行可以存一个bitset,会比用bool更快(快32倍?). 本题告诉我们一个道理: 高斯消元之后,每个变量的含义不变(虽然交换了两 ...
- 計蒜客/小教官(xjb)
題目鏈接:https://nanti.jisuanke.com/t/366 題意:中文題誒~ 思路: 先通過給出的條件構造一個符合題意的數組(可以是任意一個符合條件的數組,菜雞不會證明: 然後構造的數 ...
- [Xcode 实际操作]一、博主领进门-(10)Xcode右侧界面介绍
目录:[Swift]Xcode实际操作 本文将演示Xcode右侧界面介绍. 在项目导航区,打开视图控制器的代码文件[ViewController.swift] 右上角第三个[辅助编辑器]按钮,将代码切 ...