题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=2434

题解:

我写的是离线做法,不知道有没有在线做法。

转化一波题意,\(x\)在AC自动机上代表的字符串在\(y\)代表的字符串中出现的次数等于\(x\)在fail树的子树内有多少个点是\(y\)点Trie树上的祖先。

然后不难得到做法: 将询问离线按照\(y\)在AC自动机上的id排序(一个正常的构建Trie的方式建出来应该就满足节点的编号是它的Trie树DFS序).

在Trie树上DFS, 同时回答询问, 用树状数组维护即可

代码

  1. #include<cstdio>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<algorithm>
  5. using namespace std;
  6. const int N = 1e5;
  7. const int S = 26;
  8. struct Edge
  9. {
  10. int v,nxt;
  11. } e[(N<<1)+3];
  12. struct Query
  13. {
  14. int x,y,id;
  15. bool operator <(const Query &arg) const
  16. {
  17. return y<arg.y;
  18. }
  19. } qr[N+3];
  20. int fe[N+3];
  21. int dfn[N+3];
  22. int fa[N+3];
  23. int son[N+3][S+3];
  24. int fail[N+3];
  25. char str[N+3];
  26. int stk[N+3];
  27. int id[N+3];
  28. int que[N+3];
  29. int bit[N+3];
  30. int ord[N+3];
  31. int ans[N+3];
  32. int sz[N+3];
  33. int n,q,siz,m,cnt,en;
  34. void addval(int lrb,int val)
  35. {
  36. while(lrb<=cnt)
  37. {
  38. bit[lrb] += val;
  39. lrb += (lrb&(-lrb));
  40. }
  41. }
  42. int querysum(int rb)
  43. {
  44. int ret = 0;
  45. while(rb)
  46. {
  47. ret += bit[rb];
  48. rb -= (rb&(-rb));
  49. }
  50. return ret;
  51. }
  52. void addedge(int u,int v)
  53. {
  54. en++; e[en].v = v;
  55. e[en].nxt = fe[u]; fe[u] = en;
  56. }
  57. void buildTrie()
  58. {
  59. int u = 0,tp = 0; stk[tp] = 0;
  60. for(int i=1; i<=n; i++)
  61. {
  62. if(str[i]=='B')
  63. {
  64. stk[tp] = 0; tp--;
  65. u = stk[tp];
  66. }
  67. else if(str[i]=='P')
  68. {
  69. m++; id[m] = u;
  70. }
  71. else
  72. {
  73. str[i]-=96;
  74. if(!son[u][str[i]]) {siz++; son[u][str[i]] = siz;}
  75. u = son[u][str[i]];
  76. tp++; stk[tp] = u;
  77. }
  78. }
  79. }
  80. void buildACA()
  81. {
  82. int head = 1,tail = 0;
  83. for(int i=1; i<=S; i++) {if(son[0][i]) {tail++; que[tail] = son[0][i];} fail[son[0][i]] = 0;}
  84. while(head<=tail)
  85. {
  86. int u = que[head]; head++;
  87. addedge(fail[u],u); addedge(u,fail[u]);
  88. for(int i=1; i<=S; i++)
  89. {
  90. if(son[u][i]) {fail[son[u][i]] = son[fail[u]][i]; tail++; que[tail] = son[u][i];}
  91. else {son[u][i] = son[fail[u]][i];}
  92. }
  93. }
  94. }
  95. void dfs(int u)
  96. {
  97. cnt++; dfn[u] = cnt;
  98. sz[u] = 1;
  99. for(int i=fe[u]; i; i=e[i].nxt)
  100. {
  101. if(e[i].v==fa[u]) continue;
  102. fa[e[i].v] = u;
  103. dfs(e[i].v);
  104. sz[u] += sz[e[i].v];
  105. }
  106. }
  107. int main()
  108. {
  109. scanf("%s",str+1); n = strlen(str+1);
  110. scanf("%d",&q);
  111. buildTrie();
  112. buildACA();
  113. for(int i=1; i<=q; i++)
  114. {
  115. int x,y; scanf("%d%d",&x,&y);
  116. qr[i].x = id[x]; qr[i].y = id[y]; qr[i].id = i;
  117. }
  118. dfs(0);
  119. sort(qr+1,qr+q+1);
  120. int u = 0,tp = 0,j = 0; stk[tp] = 0; addval(dfn[u],0);
  121. for(int i=1; i<=n; i++)
  122. {
  123. if(str[i]=='B')
  124. {
  125. addval(dfn[u],-1);
  126. stk[tp] = 0; tp--;
  127. u = stk[tp];
  128. }
  129. else if(str[i]=='P')
  130. {
  131. while(j<q && qr[j+1].y==u)
  132. {
  133. j++;
  134. ans[qr[j].id] = querysum(dfn[qr[j].x]+sz[qr[j].x]-1)-querysum(dfn[qr[j].x]-1);
  135. }
  136. }
  137. else
  138. {
  139. u = son[u][str[i]];
  140. tp++; stk[tp] = u;
  141. addval(dfn[u],1);
  142. }
  143. }
  144. for(int i=1; i<=q; i++)
  145. {
  146. printf("%d\n",ans[i]);
  147. }
  148. return 0;
  149. }

BZOJ 2434 Luogu P2414 [NOI2011]阿狸的打字机 (AC自动机、树状数组)的更多相关文章

  1. 【BZOJ】2434: [Noi2011]阿狸的打字机 AC自动机+树状数组+DFS序

    [题意]阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母. 经阿狸研究发现,这个打字机是这样工作的: l 输入小写 ...

  2. [NOI2011]阿狸的打字机 --- AC自动机 + 树状数组

    [NOI2011] 阿狸的打字机 题目描述: 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机. 打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母.经阿狸研究发现, ...

  3. BZOJ2434: [Noi2011]阿狸的打字机(AC自动机 树状数组)

    Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 4140  Solved: 2276[Submit][Status][Discuss] Descript ...

  4. [BZOJ2434][Noi2011]阿狸的打字机 AC自动机+树状数组+离线

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2434 题目中这种多个串匹配的问题,一下子就想到了AC自动机.然后发现如果要建立AC自动机, ...

  5. BZOJ.2434.[NOI2011]阿狸的打字机(AC自动机 树状数组 DFS序)

    题目链接 首先不需要存储每个字符串,可以将所有输入的字符依次存进Trie树,对于每个'P',记录该串结束的位置在哪,以及当前节点对应的是第几个串(当前串即根节点到当前节点):对于'B',只需向上跳一个 ...

  6. bzoj 2434 阿狸的打字机 - Aho-Corasick自动机 - 树状数组

    题目传送门 传送站I 传送站II 题目大意 阿狸有一个打字机,它有3种键: 向缓冲区追加小写字母 P:打印当前缓冲区(缓冲区不变) B:删除缓冲区中最后一个字符 然后多次询问第$x$个被打印出来的串在 ...

  7. P2414 [NOI2011]阿狸的打字机 AC自动机

    题意 给定n个模式串,有m个询问,每次询问第X个模式串在第Y个模中出现了多少次 解题思路 以fail树相反的方向建一棵树T,问题转化为X的子树中有多少个y的终止节点.跑出T的dfs序,X的子树就可以表 ...

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

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

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

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

随机推荐

  1. HDU 5862Counting Intersections

    Counting Intersections Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/ ...

  2. c++中读写文件操作

    读写文件这个,不常用,每次用的时候都会百度一下,每次写法还都不一样,所有总是记混.今天利用点时间总结下之前工程中用过的.以后就安照这种方法写了. 搞acmicpc的时候喜欢用freopen(),这个是 ...

  3. tiny4412 裸机程序 三、关闭看门狗和调用C程序【转】

    本文转载自:http://blog.csdn.net/eshing/article/details/37112779 一.原理说明 上是章中大家可能有会觉得奇怪,CPU不是有看门狗嘛?为什么CPU没有 ...

  4. git ldap

    https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/README.md ldap : enabled : true host : 'ope ...

  5. C++11 function使用

    function是一组函数对象包装类的模板,实现了一个泛型的回调机制. 引入头文件 #include <functional>using namespace std;using names ...

  6. 特征选择--->卡方选择器

    特征选择(Feature Selection)指的是在特征向量中选择出那些“优秀”的特征,组成新的.更“精简”的特征向量的过程.它在高维数据分析中十分常用,可以剔除掉“冗余”和“无关”的特征,提升学习 ...

  7. Android开发中常用的一些小技巧(转载)

    http://www.jb51.net/article/61135.htm Activity.startActivities() 常用于在应用程序中间启动其他的Activity. TextUtils. ...

  8. Weblogic 启动慢解决方法

      添加 启动参数  :      -Xms256m -Xmx512m -XX:MaxPermSize=256m 原因 : 实际是JVM在Linux下的bug:他想调用一个随机函数,但是取不到. 暂时 ...

  9. Java初级面试模拟1

    1.简单介绍一下你的项目,说一下项目有什么模块 2.说说常见的集合有哪些吧 答:Map接口和Collection接口是所有集合框架的父接口: Collection接口的子接口包括:Set接口和List ...

  10. linux tmux基本操作

    1. 安装工具 Centos : yum install tmux 2. 基本操作 新建会话:tmux new -s session-name 查看会话:tmux ls 进入会话:tmux a -t ...