bzoj 2434 [Noi2011]阿狸的打字机 [AC自动机+树状数组]
来源:互联网 发布:淘宝网电动工具 编辑:程序博客网 时间:2024/06/06 05:08
Description
阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机。打字机上只有28个按键,分别印有26个小写英文字母和'B'、'P'两个字母。经阿狸研究发现,这个打字机是这样工作的:| 输入小写字母,打字机的一个凹槽中会加入这个字母(这个字母加在凹槽的最后)。| 按一下印有'B'的按键,打字机凹槽中最后一个字母会消失。| 按一下印有'P'的按键,打字机会在纸上打印出凹槽中现有的所有字母并换行,但凹槽中的字母不会消失。例如,阿狸输入aPaPBbP,纸上被打印的字符如下:aaaab我们把纸上打印出来的字符串从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
aPaPBbP31 21 32 3
Sample Output
210
HINT
1<=N<=10^51<=M<=10^5输入总长<=10^5
Solution
首先建立AC自动机,然后根据fail指针建一棵树,如果fail[i] = j那么j就是i的父亲。
然后对于一组询问(x,y),如果y中的某一节点在x的子树中,则答案+1。
我们可以先求出fail树的dfs序,然后按照输入的顺序dfs,此时对于一组询问,只要统计dfs序中两个x之间有多少个数就行了。可以用树状数组维护。
#include <cstdio>#include <cstring>#include <algorithm>#include <iostream>#include <queue>#include <vector>#include <utility>#define pii pair<int, int>#define mp(i, j) make_pair(i, j)using namespace std;const int MAXN = 100010;int s[MAXN];int lowbit(int x) { return x & -x;}void add(int x, int v) { while (x < MAXN) { s[x] += v; x += lowbit(x); }}int get(int x) { int ans = 0; while (x) { ans += s[x]; x -= lowbit(x); } return ans;}int fa[MAXN], next[MAXN][26], fail[MAXN];int tot = 0;char str[MAXN];int strmap[MAXN];int strcnt = 0;void init_trie() { int pos = 0, len = strlen(str); for (int i = 0; i < len; i++) { if (str[i] == 'B') { pos = fa[pos]; } else if (str[i] == 'P') { strmap[++strcnt] = pos; } else if (str[i] >= 'a' && str[i] <= 'z') { int id = str[i] - 'a'; if (!next[pos][id]) { next[pos][id] = ++tot; fa[tot] = pos; } pos = next[pos][id]; } }}vector<int> edges[MAXN];void build_fail() { queue<int> q; q.push(0); while (!q.empty()) { int p = q.front(); q.pop(); int t; for (int i = 0; i < 26; i++) { if (!(t = next[p][i])) { next[p][i] = next[fail[p]][i]; } else { fail[t] = p ? next[fail[p]][i] : 0; q.push(t); } } }}int m;vector< pii > query[MAXN];int dfn[MAXN], siz[MAXN];int ans[MAXN];int cnt = 0;void dfs(int x) { dfn[x] = ++cnt; siz[x] = 1; for (int i = 0; i < edges[x].size(); i++) { dfs(edges[x][i]); siz[x] += siz[edges[x][i]]; }}void solve() { for (int i = 1; i <= tot; i++) edges[fail[i]].push_back(i); dfs(0); int len = strlen(str); int pos = 0; for (int i = 0; i < len; i++) { if (str[i] == 'B') { add(dfn[pos], -1); pos = fa[pos]; } else if (str[i] == 'P') { for (int i = 0; i < query[pos].size(); i++) { pii temp = query[pos][i]; int root = temp.first; int r = dfn[root]; ans[temp.second] = get(r + siz[root] - 1) - get(r - 1); } } else if (str[i] >= 'a' && str[i] <= 'z') { pos = next[pos][str[i] - 'a']; add(dfn[pos], 1); } }}int main() { scanf("%s", str); init_trie(); build_fail(); scanf("%d", &m); int x, y; for (int i = 1; i <= m; i++) { scanf("%d %d", &x, &y); query[strmap[y]].push_back(mp(strmap[x], i)); } solve(); for (int i = 1; i <= m; i++) printf("%d\n", ans[i]); return 0;}
0 0
- 【BZOJ】2434: [Noi2011]阿狸的打字机 AC自动机+树状数组
- bzoj 2434 [Noi2011]阿狸的打字机 [AC自动机+树状数组]
- [AC自动机 fail树 树状数组] BZOJ 2434 [NOI2011] 阿狸的打字机
- BZOJ 2434: [Noi2011]阿狸的打字机【AC自动机,fail树.dfs序,树状数组
- 【BZOJ 2434】[Noi2011]阿狸的打字机 Ac自动机+树状数组+dfs序
- bzoj 2434: [Noi2011]阿狸的打字机 AC自动机+树状数组
- bzoj 2434 (NOI2011)阿狸的打字机 【AC自动机】【树状数组】【DFS序】
- [BZOJ]2434: [Noi2011]阿狸的打字机 AC自动机+树状数组
- bzoj 2434 [Noi2011]阿狸的打字机(AC自动机+fail树+dfs序+树状数组)
- ★【AC自动机】【树状数组】【NOI2011】阿狸的打字机
- [NOI2011]阿狸的打字机(AC自动机+树状数组)
- BZOJ 2434 阿狸的打字机 (AC自动机 + 树状数组)
- 【AC自动机】 BZOJ 2434 [Noi2011]阿狸的打字机
- [BZOJ2434]NOI2011阿狸的打字机|AC自动机|fail树|树状数组
- BZOJ2434 [Noi2011]阿狸的打字机【AC自动机+dfs序+树状数组】
- 【bzoj2434】[Noi2011]阿狸的打字机 AC自动机+fail树+dfs序+树状数组
- [BZOJ2434][NOI2011]阿狸的打字机(AC自动机+树状数组)
- 【bzoj2434】【NOI2011】【阿狸的打字机】【AC自动机+dfs序+树状数组】
- 智能指针总结
- 考生心得:SAT阅读考试常见问题解答
- Eclipse全局搜索
- 【基础练习】【快速幂】codevs3500 快速幂入门题解
- git工程的readme的常用排版命令
- bzoj 2434 [Noi2011]阿狸的打字机 [AC自动机+树状数组]
- centos 系统安装KVM
- List,Set,Map用法以及区别
- 操作系统实验六——死锁问题实验
- jQuery 教程
- The bundle does not contain an app icon for iPhone / iPod Touch of exactly '120x120' pixels, in .pn
- Java 汉字转拼音首字母缩写
- 蓝牙驱动
- iOS开发-控制状态栏