ac自动机,bit,dfs序。

本文所有的stl都是因为自己懒得实现。

 

首先x在y里面出现,就意味y节点可以顺着fail回去。

反向建出一个fail数,然后搞出dfs序列。找出x对应的区间有多少个y。

再用离线操作,把每个y需要计算的x事先保存下来。

  1. #include<cstdio>
  2. #include<algorithm>
  3. #include<cstring>
  4. #include<queue>
  5. #include<vector>
  6. using namespace std;
  7. const int maxn = 100000 + 10;
  8.  
  9. char s[maxn];
  10. int a[maxn][26];
  11. int g[maxn],v[maxn],next[maxn],eid;
  12. int pos[maxn],cnt;
  13. int fa[maxn],fail[maxn],L[maxn],R[maxn],query[maxn][3];
  14. int m,n,u,dfn,vid;
  15. vector<int> Q[maxn];
  16. queue<int> q;
  17.  
  18. struct BIT {
  19. int a[maxn<<1],n;
  20.  
  21. int lowbit(int x) {
  22. return (x & -x);
  23. }
  24.  
  25. void add(int x,int d) {
  26. //printf("c %d %d\n",x,d);
  27. for(;x<=n;x+=lowbit(x)) a[x]+=d;
  28. //printf("c");
  29. }
  30.  
  31. int query(int x) {
  32. int res=0;
  33. for(;x;x-=lowbit(x)) res+=a[x];
  34. return res;
  35. }
  36.  
  37. void init(int _n) {
  38. n=_n;
  39. }
  40. }bit;
  41.  
  42. void addedge(int a,int b) {
  43. v[eid]=b; next[eid]=g[a]; g[a]=eid++;
  44. }
  45.  
  46. void dfs(int u) {
  47. L[u]=++dfn;
  48. for(int i=g[u];~i;i=next[i]) dfs(v[i]);
  49. R[u]=dfn;
  50. }
  51.  
  52. void get_trie() {
  53. for(int i=0;i<26;i++) a[0][i]=1;
  54.  
  55. int p=1,c;vid=1;
  56. for(int i=0;i<n;i++) {
  57. //printf("f[%d] = %d\n",i,p);
  58. if(s[i]=='P') pos[++cnt]=p;
  59. else if(s[i]=='B') p=fa[p];
  60. else {
  61. c=s[i]-'a';
  62. if(!a[p][c])
  63. a[p][c]=++vid,fa[vid]=p;
  64. p=a[p][c];
  65. }
  66. //printf("f[%d] = %d\n",i,p);
  67. }
  68. }
  69.  
  70. void debug(int p) {
  71. }
  72.  
  73. void get_fail() {
  74. fail[1]=0;
  75. q.push(1);
  76.  
  77. while(!q.empty()) {
  78. u=q.front();q.pop();
  79. for(int k=0,p;k<26;k++)
  80. if(a[u][k]) {
  81. for(p=fail[u];p&&!a[p][k];p=fail[p]);
  82. fail[a[u][k]]=a[p][k];
  83. q.push(a[u][k]);
  84. }
  85. }
  86. }
  87.  
  88. void get_tree() {
  89. for(int i=1;i<=vid;i++) addedge(fail[i],i);
  90. dfs(1);
  91. }
  92.  
  93. void build() {
  94. memset(g,-1,sizeof(g));
  95. scanf("%s",s);n=strlen(s);
  96.  
  97. get_trie();
  98. //debug(1);
  99. get_fail();
  100. get_tree();
  101.  
  102. scanf("%d",&m);
  103. for(int i=1;i<=m;i++) {
  104. scanf("%d %d",&query[i][0],&query[i][1]);
  105. query[i][0]=pos[query[i][0]];
  106. query[i][1]=pos[query[i][1]];
  107. Q[query[i][1]].push_back(i);
  108. }
  109.  
  110. }
  111.  
  112. void solve() {
  113. bit.init(n<<1);
  114. int p=1;
  115. for(int i=0;i<n;i++) {
  116. //printf("s[i]=%c\n",s[i]);
  117. if(s[i]=='P') for(int j=0;j<Q[p].size();j++)
  118. query[Q[p][j]][2]=bit.query(R[query[Q[p][j]][0]])-bit.query(L[query[Q[p][j]][0]]-1);
  119. else if(s[i]=='B') bit.add(L[p],-1),p=fa[p];
  120. else p=a[p][s[i]-'a'],bit.add(L[p],1);
  121. //printf(" %d\n",i);
  122. }
  123.  
  124. for(int i=1;i<=m;i++) printf("%d\n",query[i][2]);
  125. }
  126.  
  127. int main() {
  128. build();
  129. solve();
  130.  
  131. return 0;
  132. }

2434: [Noi2011]阿狸的打字机的更多相关文章

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

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

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

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

  3. bzoj 2434 [Noi2011]阿狸的打字机 AC自动机

    [Noi2011]阿狸的打字机 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 4001  Solved: 2198[Submit][Status][D ...

  4. 2434: [Noi2011]阿狸的打字机 - BZOJ

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

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

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

  6. 【刷题】BZOJ 2434 [Noi2011]阿狸的打字机

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

  7. BZOJ 2434: [Noi2011]阿狸的打字机 AC自动机+fail树+线段树

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

  8. bzoj 2434 [Noi2011]阿狸的打字机(fail树+离线处理+BIT)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2434 [题意] 按照一定规则生成n个字符串,回答若干个询问:(x,y),问第x个字符串 ...

  9. BZOJ 2434 [Noi2011]阿狸的打字机(AC自动机)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2434 [题目大意] 给出一个打印的过程,'a'-'z'表示输入字母,P表示打印该字符串 ...

  10. bzoj 2434 [Noi2011]阿狸的打字机——AC自动机

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2434 dfs AC自动机,走过的点权值+1,回溯的时候权值-1:走到询问的 y 串的节点,看 ...

随机推荐

  1. Jquery实现图片左右自动滚动

    图片左右滚动的效果想必大家都有见到过吧,其实很简单.在本文将为大家介绍下使用Jquery是如何实现图片左右自动滚动的. 代码如下:<!DOCTYPE HTML>  <html> ...

  2. 如何实现zs无限期试用

    要删除的文件有两个,分别是.zs与10_0..zs保存的是版本号,10_0保存的是注册码,这两个文件存在的原理是:zend studio 每次启动的会检查这两个文件的创建时间,和当前日期对比,超过30 ...

  3. linux 输入子系统(4)---- input子系统的初始化

    Input子系统的初始化函数为input_init(),如下: static int __init input_init(void) { int err; input_init_abs_bypass( ...

  4. 使用OpenXml操作Excel,以下方法用于在添加列时修改Cell的CellReference属性。

    以下方法实现了递增Excel中单元格的CellReference的功能,只支持两位字母. public static string CellReferenceIncrement(string cell ...

  5. redis缓存的安装和使用

    Redis介绍    Redis本质上一个Key/Value数据库,与Memcached类似的NoSQL型数据库,但是他的数据可以持久化的保存在磁盘上,解决了服务重启后数据不丢失的问题,他的值可以是s ...

  6. cocos2dx之Lua调用C++

    现在cocos2dx3.8自己封装了以前的toLua++,比以前更好用了. 先来看一下整体步骤: 1.编写一个.ini文件. 2,修改genbindings.py脚本. 3,执行genbindings ...

  7. css tricks

    http://css-tricks.com/styling-cross-browser-compatible-range-inputs-css/ http://css-tricks.com/brows ...

  8. C# - 高级方法参数

    可选参数 -必须有个默认值,默认值必须是字面值,常量值,新对象实例或者默认值类型值. public List<string> GetWords( string sentence, bool ...

  9. c++ 读写锁

    #ifndef THREAD_UTIL_H #define THREAD_UTIL_H #include <pthread.h> namespace spider { class Auto ...

  10. 【莫比乌斯反演】关于Mobius反演与lcm的一些关系与问题简化(BZOJ 2154 crash的数字表格&&BZOJ 2693 jzptab)

    BZOJ 2154 crash的数字表格 Description 今天的数学课上,Crash小朋友学习了最小公倍数(Least Common Multiple).对于两个正整数a和b,LCM(a, b ...