题意

https://loj.ac/problem/2444

思路

​多串匹配,考虑 \(\text{AC}\) 自动机。模拟打字的过程,先建出一棵 \(\text{Trie}\) 树,把它变成自动机。对于每一个询问 \((x,y)\) ,相当于求 \(y\) 在 \(\text{Trie}\) 上的父节点中,有多少个是 \(x\) 在 \(\text{fail}\) 树上的子节点。

不难想到离线,我们对于 \(y\) 记录所有 \(x\) ,求出 \(\text{fail}\) 树上的 \(\text{dfs}\) 序并在 \(\text{Trie}\) 树上 \(\text{dfs}\) ,通过主席树维护遍历到每个点时 \(\text{fail}\) 树 \(\text{dfs}\) 序的信息,每遍历到一个点就把它在 \(\text{fail}\) 树上的 \(\text{dfs}\) 序记进主席树里,并回答在这个点上的所有询问即可。

代码

  1. #include<bits/stdc++.h>
  2. #define FOR(i,x,y) for(int i=(x),i##END=(y);i<=i##END;++i)
  3. #define DOR(i,x,y) for(int i=(x),i##END=(y);i>=i##END;--i)
  4. #define x first
  5. #define y second
  6. using namespace std;
  7. template<typename T,typename _T>inline bool chk_min(T &x,const _T y){return y<x?x=y,1:0;}
  8. template<typename T,typename _T>inline bool chk_max(T &x,const _T y){return x<y?x=y,1:0;}
  9. typedef long long ll;
  10. typedef pair<int,int> pii;
  11. const int N=1e5+5;
  12. const int NN=N*40;
  13. template<const int maxn,const int maxm>struct Linked_list
  14. {
  15. int head[maxn],to[maxm],nxt[maxm],tot;
  16. Linked_list(){clear();}
  17. void clear(){memset(head,-1,sizeof(head));tot=0;}
  18. void add(int u,int v){to[++tot]=v,nxt[tot]=head[u],head[u]=tot;}
  19. #define EOR(i,G,u) for(int i=G.head[u];~i;i=G.nxt[i])
  20. };
  21. struct ChairmanTree
  22. {
  23. int rt[N],lson[NN],rson[NN],sum[NN];
  24. int tot;
  25. int &operator [](const int x){return rt[x];}
  26. void build()
  27. {
  28. memset(rt,0,sizeof(rt));
  29. sum[tot=0]=lson[0]=rson[0]=0;
  30. }
  31. void create(int &k)
  32. {
  33. sum[++tot]=sum[k],lson[tot]=lson[k],rson[tot]=rson[k];
  34. k=tot;
  35. }
  36. void update(int &k,int x,int val,int l,int r)
  37. {
  38. create(k);
  39. if(l==r){sum[k]+=val;return;}
  40. int mid=(l+r)>>1;
  41. if(x<=mid)update(lson[k],x,val,l,mid);
  42. else update(rson[k],x,val,mid+1,r);
  43. sum[k]=sum[lson[k]]+sum[rson[k]];
  44. }
  45. int query(int k,int L,int R,int l,int r)
  46. {
  47. if(L<=l&&r<=R)return sum[k];
  48. int mid=(l+r)>>1;
  49. if(R<=mid)return query(lson[k],L,R,l,mid);
  50. else if(L>mid)return query(rson[k],L,R,mid+1,r);
  51. else return query(lson[k],L,R,l,mid)+query(rson[k],L,R,mid+1,r);
  52. }
  53. };
  54. Linked_list<N,N>G;
  55. ChairmanTree CT;
  56. int fa[N],son[N][26],ch[N][26],f[N],idx[N];
  57. int L[N],R[N],ord;
  58. int rt,tot;
  59. string str;
  60. int n,m;
  61. vector<pii>vec[N];
  62. int Output[N];
  63. void build(){rt=tot=0;}
  64. void create(int &k)
  65. {
  66. if(!k)
  67. {
  68. k=++tot;
  69. FOR(i,0,25)son[k][i]=ch[k][i]=0;
  70. }
  71. }
  72. void get_fail()
  73. {
  74. queue<int>Q;
  75. while(!Q.empty())Q.pop();
  76. f[rt]=rt;
  77. FOR(i,0,25)
  78. {
  79. if(ch[rt][i])f[ch[rt][i]]=rt,Q.push(ch[rt][i]);
  80. else ch[rt][i]=rt;
  81. }
  82. while(!Q.empty())
  83. {
  84. int u=Q.front();Q.pop();
  85. FOR(i,0,25)
  86. {
  87. if(ch[u][i])f[ch[u][i]]=ch[f[u]][i],Q.push(ch[u][i]);
  88. else ch[u][i]=ch[f[u]][i];
  89. }
  90. }
  91. }
  92. void dfs_fail(int u)
  93. {
  94. L[u]=++ord;
  95. EOR(i,G,u)dfs_fail(G.to[i]);
  96. R[u]=ord;
  97. }
  98. void init(string &str)
  99. {
  100. create(rt);
  101. fa[rt]=rt;
  102. int now=rt;
  103. FOR(i,0,str.length()-1)
  104. {
  105. char a=str[i];
  106. if(a>='a'&&a<='z')
  107. {
  108. if(!ch[now][a-'a'])
  109. {
  110. create(ch[now][a-'a']);
  111. son[now][a-'a']=ch[now][a-'a'];
  112. fa[son[now][a-'a']]=now;
  113. }
  114. now=ch[now][a-'a'];
  115. }
  116. else if(a=='P')
  117. {
  118. n++;
  119. idx[n]=now;
  120. }
  121. else if(a=='B')now=fa[now];
  122. }
  123. }
  124. void dfs_trie(int u)
  125. {
  126. CT.update(CT[u],L[u],1,1,tot);
  127. FOR(i,0,(int)vec[u].size()-1)
  128. {
  129. int x=vec[u][i].x,id=vec[u][i].y;
  130. Output[id]=CT.query(CT[u],L[x],R[x],1,tot);
  131. }
  132. FOR(i,0,25)if(son[u][i])
  133. {
  134. CT[son[u][i]]=CT[u];
  135. dfs_trie(son[u][i]);
  136. }
  137. }
  138. int main()
  139. {
  140. cin>>str>>m;
  141. init(str);
  142. FOR(i,1,m)
  143. {
  144. int x,y;
  145. scanf("%d%d",&x,&y);
  146. vec[idx[y]].push_back(pii(idx[x],i));
  147. }
  148. get_fail();
  149. FOR(i,1,tot)if(f[i]!=i)G.add(f[i],i);
  150. ord=0;dfs_fail(rt);
  151. CT.build();
  152. dfs_trie(rt);
  153. FOR(i,1,m)printf("%d\n",Output[i]);
  154. return 0;
  155. }

NOI 2011 阿狸的打字机(AC自动机+主席树)的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. eclipse maven install没反应解决办法

    .打开eclipse的Window菜单-->java-->Installed JREs .点击用的jdk,edit,在Default VM arguments里面填入-Dmaven.mul ...

  2. python中函数嵌套、函数作为变量以及闭包的原理

    嵌套函数: python允许创建嵌套函数.也就是说我们可以在函数里面定义函数,而且现有的作用域和变量生存周期依旧不变. 例子: #encoding=utf-8 def outer():    name ...

  3. こだわり者いろはちゃん / Iroha's Obsession (暴力枚举)

    题目链接:http://abc042.contest.atcoder.jp/tasks/arc058_a Time limit : 2sec / Memory limit : 256MB Score ...

  4. 使用Fiddler测试WebApi接口

    Fiddler是好用的WebApi调试工具之一,它能记录所有客户端和服务器的http和https请求,允许你监视,设置断点,甚至修改输入输出数据,Fiddler 是以代理web服务器的形式工作的,使用 ...

  5. SQL Server双机热备之后项目的FailOver自动连接

    SQL Server配置数据库镜像后,可能有朋友们会比较有疑惑,你一下搞两个数据库出来,他们的ip地址都不一样,到时候数据库切换过去了,我的数据库的连接字符串可如何是好?难道还得在代码中去控制是连接哪 ...

  6. flask框架----flask基础

    知识点回顾 1.flask依赖wsgi,实现wsgi的模块:wsgiref,werkzeug,uwsgi 2.实例化Flask对象,里面是有参数的 app = Flask(__name__,templ ...

  7. String小案例(**)、包装类型和普通数据类型的转换(拆装箱)

    ###String用法: package StringTest; /**功能: * 判断Java文件名是否正确,判断邮箱格式是否正确 * 其中:合法的文件名应该以.java结尾 * 合法的邮箱名至少包 ...

  8. oracle 18c的版本号规则

    18C之后的版本标识 从2017年7月开始,Oracle改变了以往的数据库软件发布流程,采用年度Release和季度更新的策略. Yearly Release 将之前的N年一发布更改为每年一发布.每年 ...

  9. Installing Moses on Ubuntu 16.04

    Installing Moses on Ubuntu 16.04 The process of installation To install requirements sudo apt-get in ...

  10. 20145320周岐浩 web安全基础实践

    20145320周岐浩 web安全基础实践 一.实验后回答问题 (1)SQL注入攻击原理,如何防御 一.SQL注入攻击原理 SQL注入攻击值得是通过构建特殊的输入作为参数传入web应用程序,而这些输入 ...