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

aPaPBbP

3

1 2

1 3

2 3

Sample Output

2

1

0

HINT

1<=N<=10^5

1<=M<=10^5
输入总长<=10^5

【分析】

  •   这道题是用AC自动机里的fail指针连成的树做的。
  •   用到fail树。
  •   首先有一个朴素算法就是找到第y个单词在trie树上的路径然后沿着每一个点的fail指针走,如果找到x就加1(想想fail指针建立的过程)。
  •   由此可以运用逆向思维,以x为根的子树沿着fail指针倒着走能找到多少个y路径上的点就说明x在y上出现过几次。每次都dfs找一遍,用树状数组维护,这样可以得到70分。
  •   同时这是一个离线算法,一遍dfs,遇到一个结束标记,就做一下这个串的询问,插一个点在树状数组+1,离开这个点时-1。
  •   对于树上每个点只插入一次,时间复杂度就得到了保证。

有一个很详细的题解:http://blog.csdn.net/huzecong/article/details/7769988

代码如下:(丑)

  1. #include<cstdio>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<iostream>
  5. #include<algorithm>
  6. #include<queue>
  7. using namespace std;
  8. #define Maxn 100100
  9. #define Maxl 100010
  10.  
  11. char s[Maxl];
  12. int p[Maxn];
  13.  
  14. struct hp
  15. {
  16. int x,y,next,id,ans;
  17. }qy[Maxn];int al;
  18.  
  19. struct node
  20. {
  21. int son[],cnt,fail;
  22. int num,rt,fa,st;
  23. }t[Maxn];int tot;
  24.  
  25. int first[Maxn],c[Maxn];
  26.  
  27. bool cmp(hp x,hp y) {return p[x.y]<p[y.y];}
  28. bool cmp2(hp x,hp y) {return x.id<y.id;}
  29.  
  30. void ins(int x,int y)
  31. {
  32. qy[++al].x=x;qy[al].y=y;
  33. qy[al].next=first[x];first[x]=al;
  34. }
  35.  
  36. void upd(int x,int f)
  37. {
  38. t[x].cnt=;t[x].fa=f;t[x].st=;
  39. memset(t[x].son,,sizeof(t[x].son));
  40. }
  41.  
  42. void read_trie()
  43. {
  44. scanf("%s",s+);
  45. int len=strlen(s+);
  46. memset(p,,sizeof(p));
  47. int now=;int ql=;tot=;
  48. for(int j=;j<=len;j++)
  49. {
  50. if(s[j]>='a'&&s[j]<='z')
  51. {
  52. int ind=s[j]-'a'+;
  53. if(!t[now].son[ind])
  54. t[now].son[ind]=++tot,upd(tot,now);
  55. now=t[now].son[ind];
  56. if(j==len) t[now].cnt++;
  57. }
  58. else if(s[j]=='B') now=t[now].fa;
  59. else p[++ql]=now;
  60. }
  61. }
  62.  
  63. queue<int > q;
  64. void build_AC()
  65. {
  66. int i,j,x,y;
  67. while(!q.empty()) q.pop();
  68. q.push();
  69. while(!q.empty())
  70. {
  71. x=q.front();
  72. y=t[x].fail;
  73. for(j=;j<=;j++)
  74. {
  75. if(t[x].son[j])
  76. {
  77. q.push(t[x].son[j]);
  78. t[t[x].son[j]].fail=x?t[y].son[j]:x;
  79. ins(t[t[x].son[j]].fail,t[x].son[j]);
  80. }
  81. else t[x].son[j]=t[y].son[j];
  82. }
  83. q.pop();
  84. }
  85. }
  86.  
  87. void dfs(int x)
  88. {
  89. t[x].num=++al;t[x].rt=t[x].num;
  90. for(int i=first[x];i;i=qy[i].next)
  91. dfs(qy[i].y),t[x].rt=t[qy[i].y].rt;
  92. }
  93.  
  94. void add(int x,int y)
  95. {
  96. for(int i=x;i<=tot+;i+=i&(-i))
  97. c[i]+=y;
  98. }
  99.  
  100. int getsum(int x)
  101. {
  102. int ans=;
  103. for(int i=x;i>=;i-=i&(-i))
  104. ans+=c[i];
  105. return ans;
  106. }
  107.  
  108. void dfs2(int x)
  109. {
  110. add(t[x].num,);
  111. if(t[x].st!=)
  112. {
  113. for(int i=t[x].st;;i++)
  114. {
  115. if(p[qy[i].y]!=x) break;
  116. qy[i].ans=getsum(t[p[qy[i].x]].rt)-getsum(t[p[qy[i].x]].num-);
  117. }
  118. }
  119. for(int i=;i<=;i++) if(t[x].son[i]&&t[t[x].son[i]].fa==x)
  120. {
  121. dfs2(t[x].son[i]);
  122. }
  123. add(t[x].num,-);
  124. }
  125.  
  126. void init()
  127. {
  128. memset(first,,sizeof(first));
  129. al=;
  130. read_trie();
  131. build_AC();al=;
  132. dfs();
  133. int m;
  134. scanf("%d",&m);
  135. for(int i=;i<=m;i++) {scanf("%d%d",&qy[i].x,&qy[i].y);qy[i].id=i;}
  136. sort(qy+,qy++m,cmp);
  137. qy[].y=;
  138. for(int i=;i<=m;i++)
  139. if(p[qy[i].y]!=p[qy[i-].y]) t[p[qy[i].y]].st=i;
  140. else t[p[qy[i].y]].st=t[p[qy[i-].y]].st;
  141. memset(c,,sizeof(c));
  142. dfs2();
  143. sort(qy+,qy++m,cmp2);
  144. for(int i=;i<=m;i++) printf("%d\n",qy[i].ans);
  145. }
  146.  
  147. int main()
  148. {
  149. init();
  150. return ;
  151. }

[BZOJ2434]

2016-06-16 16:55:20

【BZOJ2434-[Noi2011]】阿狸的打字机(AC自动机(fail树)+离线+树状数组)的更多相关文章

  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】阿狸的打字机 AC自动机 + Fail树 + DFS序 + 树状数组

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

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

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

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

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

  5. BZOJ2434:[NOI2011]阿狸的打字机(AC自动机,线段树)

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

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

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

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

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

  8. 【BZOJ2434】[NOI2011]阿狸的打字机 AC自动机+DFS序+树状数组

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

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

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

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

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

随机推荐

  1. datebox清除按钮,datebox加上清除按钮,easyui datebox加上清除按钮

    datebox加上清除按钮,easyui datebox加上清除按钮 >>>>>>>>>>>>>>>>& ...

  2. Linux安装QQ 2017

    网上有很多wineQQ,是基于2012或者2013做的,然而当安装好后登录他会提示版本过来,我在优麒麟的应用商店里找到了一个基于国际版QQ的Wine版本,这里说下安装过程. 先上两张成果图: 下载地址 ...

  3. SqlServer循环读取配置

    USE [DB_JP_BaseInfo00] GO /****** Object: StoredProcedure [dbo].[sp_wx_getAppointmentInfo_Str] Scrip ...

  4. 程序员带你十天快速入门Python,玩转电脑软件开发(四)

    本系列文章立志于从一个已经习得一门编程语言的基础之上,全面介绍Python的相关开发过程和相关经验总结.本篇文章主要是基于上一篇的程序员带你十天快速入门Python,玩转电脑软件开发(三)的基础之上, ...

  5. ASCII 对应表 CHR()

    chr(9) tab空格       chr(10) 换行      chr(13) 回车        chr(13)&chr(10) 回车换行       chr(32) 空格符      ...

  6. js--小结⑤

    js中的for循环,while循环,do...while循环和C语言的一模一样 有几个问题要提醒一下的是 1.  null是对象,即object       undefined是undefined d ...

  7. Java-Android 之应用停止错误

    在Android在手机上运行的时候: 经常会出现应用程序停止: 一: 因为触发的方法里面没有传值View 对象,方法报错

  8. Android基础问题汇总

    一.android:gravity 和android:layout_gravity的区别: android;gravity是自己的内容相对于自己的控件的位置,而android:layout_gravi ...

  9. javascript类继承系列一

    js中没有提供类(class,抽象类,接口等高级的抽象),可以用new,但new的function的对象,构造器 但在js中可以通过function来模拟类的一些特性function fun_name ...

  10. dense_rank()+hash提示改写优化SQL

    数据库环境:SQL SERVER 2005 今天看到一条SQL,返回10条数据,执行了50多S.刚好有空,就对它进行了优化,优化后1S出结果. 先看下原始SQL SELECT t1.line_no , ...