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 ...
随机推荐
- Luogu P1341 无序字母对
突然发现我现在很喜欢打图论题. 然而都是很easy的. 这道题很坑,用C++打了一遍莫名Too many or too few lines. 然后我打出了我的独门绝技Pascal.这可能是我最后一次用 ...
- [Spark][Python]sortByKey 例子
[Spark][Python]sortByKey 例子: [training@localhost ~]$ hdfs dfs -cat test02.txt00002 sku01000001 sku93 ...
- [转][南京米联ZYNQ深入浅出]第二季更新完毕课程共计16节课
[南京米联]ZYNQ第二季更新完毕课程共计16节课 [第二季ZYNQ] ...
- 关于LCA
LCA:最近公共祖先 指在有根树中,找出某两个结点u和v最近的公共祖先 如图,5,7的最近公共祖先就是3 接下来,我们来了解如何求解LCA No.1 暴力 首先想到的肯定是暴力,我们搜索,从两个节点一 ...
- 【nodejs】让nodejs像后端mvc框架(asp.net mvc)一样处理请求--请求处理结果适配篇(7/8)
文章目录 前情概要 前面一大坨一大坨的代码把route.controller.action.attribute都搞完事儿了,最后剩下一部分功能就是串起来的调用. 那接下就说个说第二个中间件,也是最后一 ...
- Sql_索引分析
「索引就像书的目录, 通过书的目录就准确的定位到了书籍具体的内容」,这句话描述的非常正确, 但就像脱了裤子放屁,说了跟没说一样,通过目录查找书的内容自然是要比一页一页的翻书找来的快,同样使用的索引的人 ...
- MATLAB找不到遗传算法工具箱,用不了gatool命令的解决方案
解决方案 官方解释如下: gatool was removed as of R2015b. Use optimtool 在MATLAB R2015b前的版本可以使用gatool调用遗传算法工具箱,我测 ...
- Gitblit版本服务器环境部署记录
Gitblit介绍Gitblit 是一个纯 Java 库用来管理.查看和处理 Git 资料库.相当于 Git 的 Java 管理工具,支持linux系统.Git是分布式版本控制系统,它强调速度.数据一 ...
- C_数据结构_循环实现求阶乘
# include <stdio.h> int main(void) { int val; printf("请输入一个数字:"); printf("val = ...
- js 基础-&& || 逻辑与和逻辑或
今天百度发现一个简化长if else if 语句的方法,看起来及其强大,感觉这样虽然对系统性能提升没有帮助但是代码更简练了,分析了一番,下面先说说自己学到的理论. 首先要弄清楚js 中对于 变量, ...