传送门

考虑一下,如果串B在串A中出现过,那么A的fail指针必定直接或间接指向B

那么我们可以把fail树建起来,那么就变成B代表的节点的子树里有多少节点属于A

然后这就是一个序列统计问题,直接用dfs序+树状数组可以维护

具体的操作就是,先把每一个点有关的询问给存起来,然后等到在trie树上一遍dfs,当dfs到这个串的结束节点说明所有有关这个串的节点都被遍历到(可以在遍历的时候顺便用树状数组维护序列和),然后对每一个询问查一下子树和即可

  1. //minamoto
  2. #include<iostream>
  3. #include<cstdio>
  4. #include<cstring>
  5. #include<queue>
  6. #include<algorithm>
  7. using namespace std;
  8. const int N=;
  9. int tot=;
  10. struct node{
  11. int num,type;
  12. node(){}
  13. node(int num,int type):num(num),type(type){}
  14. };
  15. queue<node> q;
  16. int ch[N][],End[N],word,fa[N],fail[N],dis[N];
  17. inline int insert(int p,int c){
  18. if(ch[p][c]) return ch[p][c];
  19. ch[p][c]=++tot,fa[tot]=p;return tot;
  20. }
  21. inline int back(int p){return fa[p];}
  22. inline void ed(int p){End[p]=++word,dis[word]=p;}
  23. void build(){
  24. for(int i=;i<;++i)
  25. if(ch[][i])
  26. q.push(node(ch[][i],i)),fail[ch[][i]]=;
  27. while(!q.empty()){
  28. node now=q.front();q.pop();
  29. if(fail[now.num]!=){
  30. int trail=fail[fa[now.num]];
  31. while(true){
  32. if(ch[trail][now.type]){trail=ch[trail][now.type];break;}
  33. if(trail==) break;trail=fail[trail];
  34. }
  35. fail[now.num]=trail;
  36. }
  37. for(int i=;i<;++i)
  38. if(ch[now.num][i])
  39. q.push(node(ch[now.num][i],i));
  40. }
  41. }
  42. int ver[N<<],Next[N<<],head[N],E=;
  43. inline void add(int u,int v){
  44. ver[++E]=v,Next[E]=head[u],head[u]=E;
  45. }
  46. int ver1[N],Next1[N],head1[N],edge1[N],E1=;
  47. inline void add1(int u,int v,int num){
  48. ver1[++E1]=v,Next1[E1]=head1[u],head1[u]=E1,edge1[E1]=num;
  49. }
  50. int c[N<<];
  51. inline void addd(int x,int y){
  52. for(;x<=tot;x+=x&-x) c[x]+=y;
  53. }
  54. inline int sum(int x){
  55. int res=;
  56. for(;x;x-=x&-x) res+=c[x];
  57. return res;
  58. }
  59. int dfn[N],sz[N],cnt=,ans[N];
  60. bool book[N];
  61. void dfsfail(int u){
  62. dfn[u]=++cnt,sz[u]=,book[u]=true;
  63. for(int i=head[u];i;i=Next[i]){
  64. int v=ver[i];
  65. if(!book[v]) dfsfail(v),sz[u]+=sz[v];
  66. }
  67. }
  68. void dfstrie(int u){
  69. addd(dfn[u],);
  70. if(End[u]){
  71. for(int i=head1[End[u]];i;i=Next1[i]){
  72. int v=ver1[i],x=dis[v];
  73. // printf("%d %d %d\n",v,x,edge1[i]);
  74. ans[edge1[i]]=sum(dfn[x]+sz[x]-)-sum(dfn[x]-);
  75. }
  76. }
  77. for(int i=;i<;++i)
  78. if(ch[u][i]) dfstrie(ch[u][i]);
  79. addd(dfn[u],-);
  80. }
  81. char s[N];int len,m,st;
  82. int main(){
  83. // freopen("testdata.in","r",stdin);
  84. scanf("%s",s+);
  85. len=strlen(s+);
  86. for(st=;st<=len;++st)
  87. if(s[st]!='B'&&s[st]!='P') break;
  88. int p=insert(,s[st]-'a');
  89. for(int i=st+;i<=len;++i){
  90. if(s[i]=='B') p=back(p);
  91. else if(s[i]=='P') ed(p);
  92. else p=insert(p,s[i]-'a');
  93. }
  94. scanf("%d",&m);
  95. for(int i=,u,v;i<=m;++i){
  96. scanf("%d%d",&u,&v);
  97. add1(v,u,i);
  98. }
  99. build();
  100. for(int i=;i<=tot;++i)
  101. add(fail[i],i),add(i,fail[i]);
  102. dfsfail(),dfstrie();
  103. for(int i=;i<=m;++i) printf("%d\n",ans[i]);
  104. return ;
  105. }

洛谷P2414 [NOI2011]阿狸的打字机(AC自动机)的更多相关文章

  1. 洛谷 P2414 [NOI2011]阿狸的打字机 解题报告

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

  2. 洛谷P2414 - [NOI2011]阿狸的打字机

    Portal Description 首先给出一个只包含小写字母和'B'.'P'的操作序列\(s_0(|s_0|\leq10^5)\).初始时我们有一个空串\(t\),依次按\(s_0\)的每一位进行 ...

  3. 【AC自动机】【树状数组】【dfs序】洛谷 P2414 [NOI2011]阿狸的打字机 题解

        这一题是对AC自动机的充分理解和树dfs序的巧妙运用. 题目背景 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机. 题目描述 打字机上只有28个按键,分别印有26个小写英文字母和' ...

  4. BZOJ 2434 Luogu P2414 [NOI2011]阿狸的打字机 (AC自动机、树状数组)

    题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=2434 题解: 我写的是离线做法,不知道有没有在线做法. 转化一波题意,\(x\)在AC ...

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. 使用qt+ros调用摄像头遇到的问题

    当使用摄像头遇到如下问题:[usb_cam-1] process has died [pid 12288, exit code 127, cmd /opt/ros/indigo/lib/usb_cam ...

  2. HBase存储方案设计

    需求描述 将数据记录持久化存储在HBase中,需要支持如下功能: 支持高吞吐量读写操作,实时采集10,000条/秒: 支持动态添加字段: 支持服务端过滤: 支持部分字段修改. 设计方案 按列存储 优点 ...

  3. IOS 工程所支持的版本 设置

    如何设置 Base SDK 和 iOS Deployment Target ? http://leopard168.blog.163.com/blog/static/16847184420116159 ...

  4. linux 下 监控系统运行状况 命令 dstat

    推荐读文:https://linux.cn/article-3215-1.html

  5. PYTHON 爬虫笔记七:Selenium库基础用法

    知识点一:Selenium库详解及其基本使用 什么是Selenium selenium 是一套完整的web应用程序测试系统,包含了测试的录制(selenium IDE),编写及运行(Selenium ...

  6. centos7搭建redis主从复制,并模拟故障切换。

    Cntos7搭建redis主从复制,并模拟故障主从切换 主从复制搭建 主机:192.168.161.179 从机:192.168.161.180 1.        安装主redis 自己本地环境,关 ...

  7. JavaMail API的应用

    JavaMail API 是一个用于阅读.编写和发送电子消息的可选包(标准扩展),用来创建邮件用户代理(Mail User Agent,MUA)类型程序. JavaMail API 需要 JavaBe ...

  8. homebrew cask安装launch rocket【转】

    简介 brew cask是一个用命令行管理Mac下应用的工具,它是基于homebrew的一个增强工具. homebrew可以管理Mac下的命令行工具,例如imagemagick, nodejs,如下所 ...

  9. <十六>UML核心视图动态视图之状态图

    一:状态图 --->状态图显示一个状态机. --->状态机用于对模型元素的动态性进行建模.更具体地说,就是对系统行为中受事件驱动的方面进行建模. --->通常使用状态图来说明业务角色 ...

  10. python json ajax django四星聚会

    什么是json: JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.易于人阅读和编写.同时也易于机器解析和生成.它基于JavaScript Programm ...