BZOJ2434: [Noi2011]阿狸的打字机
2018-01-21 15:25
309 查看
2434: [Noi2011]阿狸的打字机
Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 3726 Solved: 2043
[Submit][Status][Discuss]
Description
阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机。打字机上只有28个按键,分别印有26个小写英文字母和'B'、'P'两个字母。经阿狸研究发现,这个打字机是这样工作的:
l 输入小写字母,打字机的一个凹槽中会加入这个字母(这个字母加在凹槽的最后)。
l 按一下印有'B'的按键,打字机凹槽中最后一个字母会消失。
l 按一下印有'P'的按键,打字机会在纸上打印出凹槽中现有的所有字母并换行,但凹槽中的字母不会消失。
例如,阿狸输入aPaPBbP,纸上被打印的字符如下:
a
aa
ab
我们把纸上打印出来的字符串从1开始顺序编号,一直到n。打字机有一个非常有趣的功能,在打字机中暗藏一个带数字的小键盘,在小键盘上输入两个数(x,y)(其中1≤x,y≤n),打字机会显示第x个打印的字符串在第y个打印的字符串中出现了多少次。
阿狸发现了这个功能以后很兴奋,他想写个程序完成同样的功能,你能帮助他么?
Input
输入的第一行包含一个字符串,按阿狸的输入顺序给出所有阿狸输入的字符。第二行包含一个整数m,表示询问个数。
接下来m行描述所有由小键盘输入的询问。其中第i行包含两个整数x, y,表示第i个询问为(x, y)。
Output
输出m行,其中第i行包含一个整数,表示第i个询问的答案。Sample Input
aPaPBbP3
1 2
1 3
2 3
Sample Output
21
0
HINT
1<=N<=10^51<=M<=10^5
输入总长<=10^5
Source
【题解】http://blog.csdn.net/lych_cys/article/details/50646799
写得太赞啦,摘一些要点
首先不难模拟操作建AC自动机
后缀数组找子串是找后缀的前缀,而AC自动机找子串是看前缀的后缀。
本题中要找x在y中出现的次数
即要问x在y的前缀的后缀中出现的次数
AC自动机上y所在链上一个点u的fail指向x的末尾v,就说明y的一个1...v前缀的后缀是x
问题转化为求y所在链有多少个fail指向x的末尾
不妨建立一个fail树,将AC自动机根0道y链末尾结点权值变为1,答案即为x末尾在fail树中子树的权值
可以看到需要修改路径、查询子树
树链剖分 + dfs序用sgt维护?
NO!
离线读入所有的x,y,按y末尾在AC自动机中节点编号大小排序,询问次序变成了建trie树的顺序
这样我们重走一遍建AC自动机的过程,每次进入一个点,该点+1,每次离开一个点,该点-1,同时检查询问,直接回答即可。
这样我们只需要支持子树查询和单点修改,dfs序 + 树状数组!
#include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <algorithm> #define lowbit(x) ((-1 * (x)) & x) inline void read(int &x) { x = 0;char ch = getchar(), c = ch; while(ch < '0' || ch > '9') c = ch, ch = getchar(); while(ch <= '9' && ch >= '0') x = x * 10 + ch - '0', ch = getchar(); if(c == '-') x = -x; } const int INF = 0x3f3f3f3f; const int MAXN = 200000 + 5; int m,ch[MAXN][30],cnt,tot,rank[MAXN],fail[MAXN],fa[MAXN],last[MAXN],tag[MAXN],q[MAXN], he, ta; char s[MAXN]; void insert() { int now = 0; for(register int i = 1;s[i] != '\0';++ i) { if(s[i] == 'B') now = fa[now]; else if(s[i] == 'P') ++ tag[now], rank[++ tot] = now; else if(ch[now][s[i] - 'a' + 1]) now = ch[now][s[i] - 'a' + 1]; else fa[++ cnt] = now, now = ch[now][s[i] - 'a' + 1] = cnt; } } void build() { he = ta = 0; for(int i = 1;i <= 26;++ i) if(ch[0][i]) q[ta ++] = ch[0][i]; while(he < ta) { int now = q[he ++]; for(int i = 1;i <= 26;++ i) { int u = ch[now][i], v = fail[now]; if(!u) continue; q[ta ++] = u; while(v && !ch[v][i]) v = fail[v]; fail[u] = ch[v][i]; last[u] = tag[fail[u]] ? fail[u] : last[fail[u]]; } } } struct Edge { int u,v,nxt; Edge(int _u, int _v, int _nxt){u = _u;v = _v;nxt = _nxt;} Edge(){} }edge[MAXN << 1]; int head[MAXN], ecnt, l[MAXN], r[MAXN], w[MAXN << 1], tot_tree; inline void insert(int a, int b) { edge[++ecnt] = Edge(a,b,head[a]); head[a] = ecnt; } void dfs(int u, int pre) { l[u] = ++ tot_tree; for(register int pos = head[u];pos != -1;pos = edge[pos].nxt) { int v = edge[pos].v; if(v == pre) continue; dfs(v, u); } r[u] = tot_tree; } void make_tree() { memset(head, -1, sizeof(head)); for(register int i = 1;i <= cnt;++ i) insert(fail[i], i), insert(i, fail[i]); dfs(0, -1); } void modify(int x, int k) { for(;x <= tot_tree;x += lowbit(x)) w[x] += k; } int ask(int x) { int sum = 0; for(;x;x -= lowbit(x)) sum += w[x]; return sum; } struct Node { int x,y,rank; }node[MAXN]; bool cmp(Node a, Node b) { return a.y < b.y; } int ans[MAXN]; void solve() { int now = 0, t = 1; for(register int i = 1;s[i] != '\0';++ i) if(s[i] == 'B') modify(l[now], - 1), now = fa[now]; else if(s[i] == 'P') while(now == node[t].y) ans[node[t].rank] = ask(r[node[t].x]) - ask(l[node[t].x] - 1), ++ t; else now = ch[now][s[i] - 'a' + 1], modify(l[now], 1); } int main() { scanf("%s", s + 1); insert(); build(); make_tree(); read(m); for(register int i = 1;i <= m;++ i) read(node[i].x), read(node[i].y), node[i].rank = i, node[i].x = rank[node[i].x], node[i].y = rank[node[i].y]; std::sort(node + 1, node + 1 + m, cmp); solve(); for(register int i = 1;i <= m;++ i) printf("%d\n", ans[i]); return 0; }
BZOJ2434
相关文章推荐
- bzoj 2434: [Noi2011]阿狸的打字机 AC自动机+树状数组
- bzoj2434【NOI2011】阿狸的打字机
- bzoj 2434 [Noi2011]阿狸的打字机(AC自动机+fail树+dfs序+树状数组)
- 【bzoj2434】【NOI2011】【阿狸的打字机】【AC自动机+dfs序+树状数组】
- bzoj2434: [Noi2011]阿狸的打字机 trie+线段树
- BZOJ2434: [Noi2011]阿狸的打字机
- [bzoj2434] [Noi2011]阿狸的打字机
- BZOJ 2434: [Noi2011]阿狸的打字机【AC自动机,fail树.dfs序,树状数组
- bzoj 2434 [Noi2011]阿狸的打字机(fail树+离线处理+BIT)
- bzoj2434: [Noi2011]阿狸的打字机
- bzoj 2434: [Noi2011]阿狸的打字机
- [BZOJ2434][NOI2011]阿狸的打字机(AC自动机+树状数组)
- 【BZOJ 2434】【NOI 2011】阿狸的打字机 fail树
- BZOJ2434【NOI2011】阿狸的打字机 <AC自动机+Fail树+树状数组>
- 【NOI2011】bzoj2434 阿狸的打字机
- AC日记——[Noi2011]阿狸的打字机 bzoj 2434
- BZOJ2434 [Noi2011]阿狸的打字机
- BZOJ2434: [Noi2011]阿狸的打字机
- NOI2011 阿狸的打字机(BZOJ2434) 题解
- 【bzoj2434】[Noi2011]阿狸的打字机 AC自动机+Dfs序+树状数组