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 ...
随机推荐
- (转)Syntax error:
但是运行时总是报下面这个错,如下: test11-loop.sh: 5: Syntax error: Bad for loop variable 几经查找语法,没有问题,后来在网上找到问题原因: 代码 ...
- BugkuCTF 计算器
前言 写了这么久的web题,算是把它基础部分都刷完了一遍,以下的几天将持续更新BugkuCTF WEB部分的题解,为了不影响阅读,所以每道题的题解都以单独一篇文章的形式发表,感谢大家一直以来的支持和理 ...
- linux下core file size设置笔记
现象说明:突然发现一台测试机器的java程序莫名其妙地没了,但是没有core dump!这就需要打开服务器的core文件生成的功能了,(即core dump文件),方便程序调试.1)core文件简介c ...
- 太白教你学python---博客分类目录
太白非技术类随笔(持续更新中...猛击这里!!!) python基础 python基础一 pytcharm安装详细教程 python基础二 python基础数据类型 Python最详细,最深入的代码块 ...
- 12.12 Daily Scrum
这周末我们会集成一下反馈活跃用户的模块. 另外,今天编译的第一次测试结束,周末这两天项目的进度会比之前加快一些. Today's Task Tomorrow's Task 丁辛 实现和菜谱相关的餐 ...
- 个人博客作业Week7(阅读文章,心得体会)
Alpha阶段结束了,内心可以说是五味杂陈.不是说我们的产品拿不上台面那般差劲,复杂的心绪主要来源于和别的队的比较,别的队才刚刚发布没多久访问量和注册量就破百了,并且还发起了找bug送红包的活动.可能 ...
- Scrum Meeting 7
第七次会议 No_00:工作情况 No_01:任务说明 待完成 已完成 No_10:燃尽图 No_11:照片记录 待更新 No_100:代码/文档签入记录 No_101:出席表 ...
- Android 學習之旅!(2)
早幾天因爲學車,弄了幾天時間和精力過去,今天終於考過了(科目二,還是補考的...)嗯..不管這麼多了..今天又開始我的android 學習之旅!! 筆記: platform-tools目錄下的文件: ...
- 小学四则运算APP 第一个冲刺阶段 第六天
团队成员:陈淑筠.杨家安.陈曦 团队选题:小学四则运算APP 第一次冲刺阶段时间:11.17~11.27 本次发布的是重新排列整齐ResultActivity的布局代码activity_result. ...
- 关于EA和ED的区别
在申请美国大学本科的过程中,申请的截止时间往往分为两轮:提前申请(Early Decision/Action) 和常规申请 (Regular Decision).提前申请,顾名思义,截止时间会相对早一 ...