Description

题库链接

给你 \(n\) 个单词, \(m\) 组询问,每组询问形同 \((x,y)\) ,询问 \(x\) 串在 \(y\) 串中出现多少次。

\(1\leq n,m\leq10^5\)

Solution

比较暴力的做法就是建好 \(AC\) 自动机后,对于每个 \(y\) 串暴力跑一遍。看看查询的时候有多少次落在了 \(x\) 串的末尾。

我们可以构建 \(fail\) 树,那么其实题目可以转变为对于 \(x\) 串末尾节点,其子树中有多少个节点位于 \(y\) 串上。

由于题目的特殊性,我们可以离线询问按照 \(y\) 来排序。并且预处理出 \(AC\) 自动机的 \(dfn\) 。

我们按照构建 \(Trie\) 树的操作再按原字符串走一遍。入栈时对应的 \(dfn\) 处 \(+1\) ,出时对应的 \(dfn\) 处 \(-1\) 。那么走到一个单词节点,所有打上标记的 \(dfn\) 都是该单词上的。

注意到一个子树内的 \(dfn\) 都是连续的,显然就可以回答所有 \(y\) 等于该单词的询问了。树状数组维护 \(dfn\) 的标记的前缀和即可。

Code

  1. //It is made by Awson on 2018.3.18
  2. #include <bits/stdc++.h>
  3. #define LL long long
  4. #define dob complex<double>
  5. #define Abs(a) ((a) < 0 ? (-(a)) : (a))
  6. #define Max(a, b) ((a) > (b) ? (a) : (b))
  7. #define Min(a, b) ((a) < (b) ? (a) : (b))
  8. #define Swap(a, b) ((a) ^= (b), (b) ^= (a), (a) ^= (b))
  9. #define writeln(x) (write(x), putchar('\n'))
  10. #define lowbit(x) ((x)&(-(x)))
  11. using namespace std;
  12. const int N = 100000;
  13. void read(int &x) {
  14. char ch; bool flag = 0;
  15. for (ch = getchar(); !isdigit(ch) && ((flag |= (ch == '-')) || 1); ch = getchar());
  16. for (x = 0; isdigit(ch); x = (x<<1)+(x<<3)+ch-48, ch = getchar());
  17. x *= 1-2*flag;
  18. }
  19. void print(int x) {if (x > 9) print(x/10); putchar(x%10+48); }
  20. void write(int x) {if (x < 0) putchar('-'); print(Abs(x)); }
  21. char ch[N+5];
  22. int n, m, idx, dfn[N+5], size[N+5], ans[N+5], mp[N+5];
  23. struct tt {int to, next; }edge[(N<<1)+5];
  24. struct qu {
  25. int x, y, id;
  26. bool operator < (const qu &b) const {return y < b.y; }
  27. }que[N+5];
  28. int path[N+5], top;
  29. void add(int u, int v) {edge[++top].to = v, edge[top].next = path[u], path[u] = top; }
  30. struct bittree {
  31. int c[N+5];
  32. void add(int o, int val) {for (; o <= idx; o += lowbit(o)) c[o] += val; }
  33. int count(int o) {int ans = 0; for (; o; o -= lowbit(o)) ans += c[o]; return ans; }
  34. }BT;
  35. struct Trie {
  36. int ch[N+5][26], pre[N+5], f[N+5], val[N+5], pos;
  37. void build(char *S) {
  38. int u = 0;
  39. for (int i = 0, len = strlen(S); i < len; i++) {
  40. if (S[i] == 'P') {val[u] = ++n, mp[n] = u; continue; }
  41. if (S[i] == 'B') {u = pre[u]; continue; }
  42. if (ch[u][S[i]-'a'] == 0) ++pos, pre[pos] = u, ch[u][S[i]-'a'] = pos;
  43. u = ch[u][S[i]-'a'];
  44. }
  45. }
  46. void get_fail() {
  47. queue<int>Q;
  48. for (int i = 0; i < 26; i++) if (ch[0][i]) f[ch[0][i]] = 0, Q.push(ch[0][i]);
  49. while (!Q.empty()) {
  50. int u = Q.front(); Q.pop();
  51. for (int i = 0; i < 26; i++) {
  52. if (ch[u][i]) f[ch[u][i]] = ch[f[u]][i], Q.push(ch[u][i]);
  53. else ch[u][i] = ch[f[u]][i];
  54. }
  55. }
  56. for (int i = 1; i <= pos; i++) add(f[i], i);
  57. }
  58. void query(char *S) {
  59. int loc = 1, u = 0;
  60. for (int i = 0, len = strlen(S); i < len; i++) {
  61. if (S[i] == 'P') {
  62. while (loc <= m && que[loc].y == val[u])
  63. ans[que[loc].id] = BT.count(dfn[mp[que[loc].x]]+size[mp[que[loc].x]]-1)-BT.count(dfn[mp[que[loc].x]]-1), ++loc;
  64. }else if (S[i] == 'B') BT.add(dfn[u], -1), u = pre[u];
  65. else u = ch[u][S[i]-'a'], BT.add(dfn[u], 1);
  66. }
  67. }
  68. }T;
  69. void dfs(int o) {
  70. size[o] = 1, dfn[o] = ++idx;
  71. for (int i = path[o]; i; i = edge[i].next) {
  72. dfs(edge[i].to); size[o] += size[edge[i].to];
  73. }
  74. }
  75. void work() {
  76. scanf("%s", ch); T.build(ch); T.get_fail();
  77. dfs(0); read(m);
  78. for (int i = 1; i <= m; i++) read(que[i].x), read(que[i].y), que[i].id = i;
  79. sort(que+1, que+1+m); T.query(ch);
  80. for (int i = 1; i <= m; i++) writeln(ans[i]);
  81. }
  82. int main() {
  83. work(); return 0;
  84. }

[NOI 2011]阿狸的打字机的更多相关文章

  1. NOI 2011 阿狸的打字机(AC自动机+主席树)

    题意 https://loj.ac/problem/2444 思路 ​多串匹配,考虑 \(\text{AC}\) 自动机.模拟打字的过程,先建出一棵 \(\text{Trie}\) 树,把它变成自动机 ...

  2. NOI 2011 阿狸的打字机 (AC自动机+dfs序+树状数组)

    题目大意:略(太长了不好描述) 良心LOJ传送门 先对所有被打印的字符串建一颗Trie树 观察数据范围,并不能每次打印都从头到尾暴力建树,而是每遍历到一个字符就在Trie上插入这个字符,然后记录每次打 ...

  3. NOI 2011 【阿狸的打字机】

    之前讲了[AC自动姬],今天我终于把这题给刚下来了...嗯,来给大家讲一讲. 题目描述: 打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母.经阿狸研究发现,这个打字机是这样工 ...

  4. BZOJ 2434: [Noi2011]阿狸的打字机 [AC自动机 Fail树 树状数组 DFS序]

    2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 2545  Solved: 1419[Submit][Sta ...

  5. 【BZOJ-2434】阿狸的打字机 AC自动机 + Fail树 + DFS序 + 树状数组

    2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 2022  Solved: 1158[Submit][Sta ...

  6. BZOJ_2434_[NOI2011]_阿狸的打字机_(AC自动机+dfs序+树状数组)

    描述 http://www.lydsy.com/JudgeOnline/problem.php?id=2434 给出\(n\)个字符串,\(m\)个询问,对于第\(i\)个询问,求第\(x_i\)个字 ...

  7. AC自动机:BZOJ 2434 阿狸的打字机

    2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 1834  Solved: 1053[Submit][Sta ...

  8. BZOJ 2434: [Noi2011]阿狸的打字机( AC自动机 + DFS序 + 树状数组 )

    一个串a在b中出现, 那么a是b的某些前缀的后缀, 所以搞出AC自动机, 按fail反向建树, 然后查询(x, y)就是y的子树中有多少是x的前缀. 离线, 对AC自动机DFS一遍, 用dfs序+树状 ...

  9. [NOI2011]阿狸的打字机(好题!!!!)

    2785: [NOI2011]阿狸的打字机 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 7  Solved: 3[Submit][Status][We ...

随机推荐

  1. 漫谈Java IO之 Netty与NIO服务器

    前面介绍了基本的网络模型以及IO与NIO,那么有了NIO来开发非阻塞服务器,大家就满足了吗?有了技术支持,就回去追求效率,因此就产生了很多NIO的框架对NIO进行封装--这就是大名鼎鼎的Netty. ...

  2. Linux下C编写基本的多线程socket服务器

    不想多说什么,会搜这些东西的都是想看代码的吧. 一开始不熟悉多线程的时候还在想怎么来控制一个线程的结束,后来发现原来有pthread_exit()函数可以直接在线程函数内部调用结束这个线程. 开始还想 ...

  3. 团队作业8——测试与发布(Beta阶段)

    Deadline: 2017-12-17 23:00PM,以博客发表日期为准.   评分基准: 按时交 - 有分,检查的项目包括后文的三个方面 测试报告 发布说明 展示博客(单独一篇博客) 晚交 - ...

  4. AWS中的Internet 网关

    nternet 网关是一种横向扩展.支持冗余且高度可用的 VPC 组件,可实现 VPC 中的实例与 Internet 之间的通信.因此它不会对网络流量造成可用性风险或带宽限制. Internet 网关 ...

  5. css变化代码2

    <!DOCTYPE html><html>    <head>        <meta charset="utf-8" />   ...

  6. openfalcon

    一.环境准备 操作系统:centos7(minimal,www.centos.org下载的包是CentOS-7-x86_64-Minimal-1611.iso) 1.1 更换阿里yum(个人习惯) 步 ...

  7. Windows Powershell脚本执行

    在cmd下执行powershell进入shell模式: 变量定义:$i = 10 $a = ifconfig | findstr "192" Windows下的命令都可以执行如: ...

  8. oracle drop table(表)数据恢复方法

    今天不小心把系统用户表给drop掉了,正在运行的系统正式库啊,还好可以恢复 一.查看数据库回收站,看删除的表是否还在回收站select object_name,original_name,partit ...

  9. MySQLdb、 flask-MySQLdb 、MySQL-python 安装失败

    今天在学习flask的时候,学习到数据库部分,连接mysql生成表,运行程序报错误:No module named MySQLdb 此时 需要安装 以下两个中任何一个 pip install flas ...

  10. leetcode算法: Find the Difference

    Given two strings s and t which consist of only lowercase letters.String t is generated by random sh ...