BZOJ 2434 阿狸的打字机 | AC自动机
AC自动机上有神奇的东西叫做fail指针……所有fail指针连起来恰好构成一棵以1为根的树!
而这道题问x在y中出现过多少次,就是问Trie树上根到y的结束节点的路径上有多少节点能通过跳fail跳到x的结束节点上,即,路径上有多少节点在fail树上在x的结束节点的子树中。
那么怎么统计答案呢?可以把询问离线,把fail树DFS一遍得到DFS序列,再把Trie树DFS一遍,DFS到它(入栈)的时候在DFS序列中对应位置+1,离开(出栈)的时候在DFS序列中对应位置-1;中间回答所有当前节点作为y的询问,方法是求对应x的子树和,即序列上的区间和。
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <vector>
#define space putchar(' ')
#define enter putchar('\n')
using namespace std;
typedef long long ll;
template <class T>
void read(T &x){
char c;
bool op = 0;
while(c = getchar(), c < '0' || c > '9')
if(c == '-') op = 1;
x = c - '0';
while(c = getchar(), c >= '0' && c <= '9')
x = x * 10 + c - '0';
if(op) x = -x;
}
template <class T>
void write(T x){
if(x < 0) putchar('-'), x = -x;
if(x >= 10) write(x / 10);
putchar('0' + x % 10);
}
const int N = 100005;
char s[N];
int n, m, tot = 1, son[N][26], real_son[N][26], fail[N], ans[N];
int st[N], ed[N], idx, adj[N], nxt[N], nod[N], sum[N];
vector <int> num[N];
struct Query {int id, x;};
vector <Query> q[N];
void add(int u, int v){
nxt[v] = adj[u], adj[u] = v;
}
void build(){
static int stk[N], que[N];
int now = 1, len = strlen(s + 1), top = 0, qr;
stk[0] = 1;
for(int i = 1; i <= len; i++)
if(s[i] == 'P') num[now].push_back(++n), nod[n] = now;
else if(s[i] == 'B') now = stk[top = max(0, top - 1)];
else{
int c = s[i] - 'a';
if(!son[now][c]) son[now][c] = ++tot;
now = son[now][c];
stk[++top] = now;
}
for(int i = 1; i <= tot; i++)
for(int j = 0; j < 26; j++)
real_son[i][j] = son[i][j];
for(int i = 0; i < 26; i++) son[0][i] = 1;
que[qr = 1] = 1;
for(int ql = 1; ql <= qr; ql++)
for(int u = que[ql], i = 0; i < 26; i++)
if(!son[u][i]) son[u][i] = son[fail[u]][i];
else{
add(fail[son[u][i]] = son[fail[u]][i], son[u][i]);
que[++qr] = son[u][i];
}
}
void dfs_fail(int u){
st[u] = ++idx;
for(int v = adj[u]; v; v = nxt[v])
dfs_fail(v);
ed[u] = idx;
}
void change(int p, int x){
while(p <= idx) sum[p] += x, p += p & -p;
}
int ask(int p){
int ret = 0;
while(p) ret += sum[p], p -= p & -p;
return ret;
}
void dfs_trie(int u){
change(st[u], 1);
for(vector<int>::iterator i = num[u].begin(); i != num[u].end(); i++)
for(vector<Query>::iterator j = q[*i].begin(); j != q[*i].end(); j++)
ans[j -> id] = ask(ed[nod[j -> x]]) - ask(st[nod[j -> x]] - 1);
for(int i = 0; i < 26; i++)
if(real_son[u][i])
dfs_trie(son[u][i]);
change(st[u], -1);
}
int main(){
scanf("%s", s + 1);
read(m);
for(int i = 1, y; i <= m; i++){
Query tmp;
read(tmp.x), read(y), tmp.id = i;
q[y].push_back(tmp);
}
build();
dfs_fail(1);
dfs_trie(1);
for(int i = 1; i <= m; i++)
write(ans[i]), enter;
return 0;
}
BZOJ 2434 阿狸的打字机 | AC自动机的更多相关文章
- BZOJ 2434 阿狸的打字机(ac自动机+dfs序+树状数组)
题意 给你一些串,还有一些询问 问你第x个串在第y个串中出现了多少次 思路 对这些串建ac自动机 根据fail树的性质:若x节点是trie中root到t任意一个节点的fail树的祖先,那么x一定是y的 ...
- bzoj 2434 阿狸的打字机 - Aho-Corasick自动机 - 树状数组
题目传送门 传送站I 传送站II 题目大意 阿狸有一个打字机,它有3种键: 向缓冲区追加小写字母 P:打印当前缓冲区(缓冲区不变) B:删除缓冲区中最后一个字符 然后多次询问第$x$个被打印出来的串在 ...
- BZOJ 2434: [Noi2011]阿狸的打字机 [AC自动机 Fail树 树状数组 DFS序]
2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 2545 Solved: 1419[Submit][Sta ...
- AC自动机:BZOJ 2434 阿狸的打字机
2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 1834 Solved: 1053[Submit][Sta ...
- BZOJ 2434: [Noi2011]阿狸的打字机( AC自动机 + DFS序 + 树状数组 )
一个串a在b中出现, 那么a是b的某些前缀的后缀, 所以搞出AC自动机, 按fail反向建树, 然后查询(x, y)就是y的子树中有多少是x的前缀. 离线, 对AC自动机DFS一遍, 用dfs序+树状 ...
- 【BZOJ】2434: [Noi2011]阿狸的打字机 AC自动机+树状数组+DFS序
[题意]阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母. 经阿狸研究发现,这个打字机是这样工作的: l 输入小写 ...
- 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】阿狸的打字机 AC自动机 + Fail树 + DFS序 + 树状数组
2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 2022 Solved: 1158[Submit][Sta ...
随机推荐
- MVC4程序运行报错
近期了解MVC4的时候弄了一个简单的小工程,使用Entity Framework作为Model,F5启动调试运行的时候没有问题,但是发布到IIS之后访问就报错 错误信息如下: The Entity F ...
- [HNOI2018]游戏[拓扑排序]
题意 题目链接 分析 先将没有锁的房间缩点,首先有一个 \(O(n^2)\) 的想法:从每个点出发,每次检查能否向两边扩张. 容易发现门和门之间如果有锁,必然只有一方能够开锁(只有一把钥匙),并且能够 ...
- Roslyn入门(一)-C#语法分析
演示环境 Visual Studio 2017 .NET Compiler Platform SDK 简介 今天,Visual Basic和C#编译器是黑盒子:输入文本然后输出字节,编译管道的中间阶段 ...
- Js基础---红宝书读书日记(1)-------基本类型和引用类型
JS的变量可能包含两种不同数据类型的值,基本类型和引用类型; 基本类型是指简单的数据段,引用类型是指可能由多个值构成的对象; JS高级程序设计第三章介绍了变量分为 5种简单数据类型(string/nu ...
- Log4net_配置
Log4net 有三个主要组件:loggers,appenders 和 layouts.这三个组件一起工作使得开发者能够根据信息类型和等级(Level)记录信息,以及在运行时控制信息的格式化和信息的写 ...
- 基于Ping和Telnet/NC的监控脚本案例分析
案例一:单纯地对某些ip进行ping监控 [root@test opt]# cat /opt/hosts_ip_list 192.168.10.10 192.168.10.11 192.168.10. ...
- linux-安装-源码安装
编译安装 tengine
- cocoapod Podfile use frameworks swift/oc混编 could not build module xxx
前置: 知名的pod: AFNetworking 我自己的pod: AFNetworking+RX 3.1.0.18 里面有一段代码是: #import <Foundation/Founda ...
- js控制css时注意
font-size:10px--------e.style.fontSize="10px " 属性名:font-size--------fontSize; 属性值:10px---- ...
- BugPhobia开发篇章:Beta阶段第IX次Scrum Meeting
0x01 :Scrum Meeting基本摘要 Beta阶段第九次Scrum Meeting 敏捷开发起始时间 2015/12/25 00:00 A.M. 敏捷开发终止时间 2015/12/28 23 ...