题目链接

problem

有\(n\)个字符串,对于第\(i\)个字符串通过以下两种方式中的一个给出。

  1. \(1\; c\),该字符串只含一个字符\(c\)。

  2. \(2\ x\ c\),该字符串为第\(x(1\le x < i)\)个字符串末尾添加一个字符\(c\)得到。

有\(m\)次询问,每次询问给出一个字符串\(s\)和位置编号\(x\),问在上述第\(x\)个字符串中,字符串\(s\)出现了几次。

solution

需要用到\(AC\)自动机,树状数组,\(dfs\)序。

首先将询问离线下来,对于所有询问的字符串建立一个\(AC\)自动机,从而求出\(fail\)树。然后利用\(fail\)树的性质:一个字符串在母串中出现的次数为将母串在AC自动机上跑一遍并将走到的位置权值+1,该字符串所对应的\(fail\)节点的子树权值和。

还有一个需要解决的问题,如果将母串在AC自动机上跑,如果暴力跑显然不行。所以我们发现他给出这\(n\) 个字符串的方式也是一棵树的形式。所以我们就可以用以下方式跑。

  1. dfs(u,p) {//u为当前节点,p为其父亲在AC自动机上所跑到的节点
  2. p移向uAC自动机上跑到的节点
  3. p所对应的的节点权值+1
  4. for(vu的儿子) dfs(v,p)
  5. 统计所有对于u这个串的查询的答案。
  6. p所对应的节点权值-1
  7. }

发现通过上面的方式,就可以保证每次查询的时候只有所查询的字符串在\(AC\)自动机上产生了贡献。

在\(fail\)树上查询子树权值和,可以用\(dfs\)序+树状数组完成。

code

  1. //@Author: wxyww
  2. #include<cstdio>
  3. #include<iostream>
  4. #include<cstdlib>
  5. #include<cstring>
  6. #include<algorithm>
  7. #include<queue>
  8. #include<vector>
  9. #include<ctime>
  10. #include<cmath>
  11. #include<map>
  12. #include<string>
  13. using namespace std;
  14. typedef long long ll;
  15. const int N = 400010;
  16. ll read() {
  17. ll x = 0,f = 1; char c = getchar();
  18. while(c < '0' || c > '9') {if(c == '-') f = -1;c = getchar();}
  19. while(c >= '0' && c <= '9') {x = x * 10 + c - '0',c = getchar();}
  20. return x * f;
  21. }
  22. char ss[N],s[N];
  23. int fail[N],trie[N][30];
  24. struct node {
  25. int v,nxt;
  26. }e[N];
  27. int idtot,siz[N],tree[N],fa[N],bh[N],ans[N],head[N],ejs,tot;
  28. void add(int u,int v) {
  29. e[++ejs].v = v;e[ejs].nxt = head[u];head[u] = ejs;
  30. }
  31. vector<pair<int,int> >que[N];
  32. void update(int pos,int c) {
  33. while(pos <= idtot) {
  34. tree[pos] += c;
  35. pos += pos & -pos;
  36. }
  37. }
  38. int query(int pos) {
  39. int ret = 0;
  40. while(pos) {
  41. ret += tree[pos];
  42. pos -= pos & -pos;
  43. }
  44. return ret;
  45. }
  46. int add(char *t) {
  47. int n = strlen(t + 1),p = 0;
  48. for(int i = 1;i <= n;++i) {
  49. if(!trie[p][t[i] - 'a']) trie[p][t[i] - 'a'] = ++tot;
  50. p = trie[p][t[i] - 'a'];
  51. }
  52. // printf("!!!%d\n",p);
  53. return p;
  54. }
  55. queue<int>q;
  56. vector<int>E[N];
  57. void build() {
  58. for(int i = 0;i < 26;++i) if(trie[0][i]) q.push(trie[0][i]);
  59. while(!q.empty()) {
  60. int u = q.front();q.pop();
  61. E[fail[u]].push_back(u);
  62. for(int i = 0;i < 26;++i) {
  63. if(!trie[u][i]) trie[u][i] = trie[fail[u]][i];
  64. else fail[trie[u][i]] = trie[fail[u]][i],q.push(trie[u][i]);
  65. }
  66. }
  67. }
  68. void AC_dfs(int u) {
  69. int k = E[u].size();
  70. bh[u] = ++idtot;siz[u] = 1;
  71. for(int i = 0;i < k;++i) {
  72. int v = E[u][i];
  73. AC_dfs(v);
  74. siz[u] += siz[v];
  75. }
  76. }
  77. int getans(int p) {
  78. // printf("!!!%d %d\n",bh[p] + siz[p] - 1,bh[p]);
  79. return query(bh[p] + siz[p] - 1) - query(bh[p] - 1);
  80. }
  81. void dfs(int u,int p) {
  82. p = trie[p][s[u] - 'a'];
  83. // if(u == 2) printf("!!!%d\n",u);
  84. update(bh[p],1);
  85. // printf("!!%d %d\n",u,s[u] - 'a');
  86. // printf("!!!%d %d\n",u,p);
  87. for(int i = head[u];i;i = e[i].nxt) dfs(e[i].v,p);
  88. int k = que[u].size();
  89. for(int i = 0;i < k;++i) ans[que[u][i].second] = getans(que[u][i].first);
  90. update(bh[p],-1);
  91. }
  92. int main() {
  93. int n = read();
  94. for(int i = 1;i <= n;++i) {
  95. int opt = read();
  96. if(opt == 2) fa[i] = read();
  97. add(fa[i],i);
  98. // cin>>s[i];
  99. scanf("%s",&s[i]);
  100. }
  101. int m = read();
  102. for(int i = 1;i <= m;++i) {
  103. int id = read();
  104. scanf("%s",ss + 1);
  105. que[id].push_back(make_pair(add(ss),i));
  106. }
  107. build();
  108. // for(int i = 0;i < 26;++i) printf("!!%d\n",trie[0][i]);
  109. // for(int i = 1;i <= tot;++i) printf("!!%d\n",fail[i]);
  110. // printf("!!%d\n",trie[1][0]);
  111. AC_dfs(0);
  112. // printf("!!!%d %d\n",tot,idtot);
  113. for(int i = 1;i <= n;++i) if(!fa[i]) dfs(i,0);
  114. for(int i = 1;i <= m;++i) printf("%d\n",ans[i]);
  115. return 0;
  116. }

CF1207G Indie Album的更多相关文章

  1. Codeforces 1207 G. Indie Album

    Codeforces 1207 G. Indie Album 解题思路 离线下来用SAM或者AC自动机就是一个单点加子树求和,套个树状数组就好了,因为这个题广义SAM不能存在 \(len[u] = l ...

  2. CodeForces - 1207G :Indie Album(AC自动机 fail树上DFS)

    题意:有N个串,给出的形式是拼接给出,对于第i行:  (1,c)表示字符串i是单个字母c: (2,p,c)表示字符串i=在字符串p后面接上一个字母c. 然后给出M个提问,形式是(i,string).问 ...

  3. CF G. Indie Album 广义后缀自动机+树链剖分+线段树合并

    这里给出一个后缀自动机的做法. 假设每次询问 $t$ 在所有 $s$ 中的出现次数,那么这是非常简单的: 直接对 $s$ 构建后缀自动机,随便维护一下 $endpos$ 大小就可以. 然而,想求 $t ...

  4. CF G. Indie Album AC自动机+fail树+线段树

    这个套路挺有意思的. 把 $trie$ 和 $fail$ 树都建出来,然后一起跑一跑就好了~ #include <queue> #include <cstdio> #inclu ...

  5. ACAM 题乱做

    之前做了不少 ACAM,不过没怎么整理起来,还是有点可惜的. 打 * 的是推荐一做的题目. I. *CF1437G Death DBMS 见 我的题解. II. *CF1202E You Are Gi ...

  6. Educational Codeforces Round 71 (Rated for Div. 2)

    传送门 A.There Are Two Types Of Burgers 签到. B.Square Filling 签到 C.Gas Pipeline 每个位置只有"高.低"两种状 ...

  7. [Codeforces Educational Round 71]Div. 2

    总结 手速场...像我这种没手速的就直接炸了... 辣鸡 E 题交互,少打了个 ? 调了半个小时... 到最后没时间 G 题题都没看就结束了...结果早上起来被告知是阿狸的打字机...看了看题一毛一样 ...

  8. Educational Codeforces Round 71

    https://www.cnblogs.com/31415926535x/p/11460682.html 上午没课,做一套题,,练一下手感和思维,,教育场的71 ,,前两到没啥,,后面就做的磕磕巴巴的 ...

  9. Educational Codeforces Round 71 (Rated for Div. 2) Solution

    A. There Are Two Types Of Burgers 题意: 给一些面包,鸡肉,牛肉,你可以做成鸡肉汉堡或者牛肉汉堡并卖掉 一个鸡肉汉堡需要两个面包和一个鸡肉,牛肉汉堡需要两个面包和一个 ...

随机推荐

  1. 第三章 HTTP报文中的HTTP信息

    第三章 HTTP报文中的HTTP信息 HTTP通信过程:客户端—>服务端,服务端—>客户端. 1.HTTP报文 使用HTTP协议交互的信息被称为HTTP报文,包括请求报文和响应报文. [请 ...

  2. [题解向] PAM简单习题

    \(1\) LG5496 [模板]回文自动机 对于 \(s\) 的每个位置,请求出以该位置结尾的回文子串个数. \(|s|\leq 1e6\) 然后就是PAM的板子题咋感觉好像没有不是很板的PAM题呢 ...

  3. Do Deep Nets Really Need to be Deep?

    url: https://arxiv.org/pdf/1312.6184.pdf year: NIPS2014 浅网络学习深网络的函数表示, 训练方法就是使用深网络的 logits(softmax i ...

  4. 前端之CSS1

    CSS基本语法和引入方式 CSS介绍 为了让网页元素的样式更加丰富,也为了让网页的内容和样式能拆分开,CSS由此而诞生,CSS是 Cascading Style Sheets 的首字母缩写,意思是层叠 ...

  5. Python爬取知乎单个问题下的回答

    前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者: 努力学习的渣渣哦 PS:如有需要Python学习资料的小伙伴可以加 ...

  6. 交互式shell脚本web console

    官网:http://web-console.org/ 这个脚本可以实现web下交互,也就是有了这玩意后可以不用反弹shell了. <?php // Web Console v0.9.7 (201 ...

  7. 使用Fiddler进行HTTP流量分析

    - 安装 Fiddler是一款免费软件,可以到其官网下载,地址是https://www.telerik.com/fiddler,也可以从我的网盘中下载,发送"fiddler"获取下 ...

  8. STM32 掉电检测程序

    当VDD下降到PVD阀值以下或当VDD上升到PVD阀值之上时,根据外部中断第16线的上升/下降边沿触发设置,就会产生PVD中断 void PVD_IRQHandler(void) { led_ctrl ...

  9. if语句,if...else语句的分析

    if语句的反汇编判断 if语句的反汇编判断基本是围绕JCC指令的,如果想要有深刻的理解,可以自行练习JCC指令 执行各类影响标志位的指令 jxx xxxx 1.案例一 mov eax,dword pt ...

  10. [b0029] python 归纳 (十四)_队列Queue实现生产者消费者

    # -*- coding: UTF-8 -*- """ 多线程的生产者,消费者 使用队列Queue """ import Queue imp ...