原题链接

题意

  • 每个测试点,一开始给我们n,m,k然后是一个长度为n的字符串。

  • 之后m次操作,1 c是往字符串后面添加一个字符c,2是查询字符串中出现k次以及以上的子串个数,m为2e5

思路

  • 首先可以看出这是在线算法(离线其实也可以),然后是查询出现至少k次的子串,这样我们可以直接联系到后缀自动机,与我们本题的需求较为契合

  • 我们知道后缀自动机中,每个节点代表的不同子串数量为

\[cnt_v = len(v) - len(link(v))
\]
  • 而每个节点的出现次数是其本身与link树的所有子树的标记次数之和,所以每次插入一个字符之后,我们都沿着link向上更新,对沿路节点的标记+1,如果出现了加完后标记正好为k的节点,则
\[ans += len(v) - len(link(v)
\]

然后如果某个节点在访问之前就达到了k,则不需要继续向上更新了,因为上面的节点也肯定大于等于k,并且在之前就被记录了

AC代码

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <iostream>
  4. #include <algorithm>
  5. using namespace std;
  6. const int N = 250000;
  7. int n, m, k, last = 0, co = 0;
  8. long long ans = 0;
  9. char ss[N + 5];
  10. struct Sam
  11. {
  12. int fl;
  13. int len;
  14. int fail;
  15. int sn[26];
  16. } sam[N * 2 + 5];
  17. void inits(int o)
  18. {
  19. sam[o].fail = -1;
  20. sam[o].len = 0;
  21. sam[o].fl = 0;
  22. for (int i = 0; i < 26; ++i)
  23. {
  24. sam[o].sn[i] = 0;
  25. }
  26. }
  27. void update(int o)
  28. {
  29. while (o > 0 && sam[o].fl < k)
  30. {
  31. ++sam[o].fl;
  32. if (sam[o].fl >= k)
  33. {
  34. ans += sam[o].len - sam[sam[o].fail].len;
  35. }
  36. o = sam[o].fail;
  37. }
  38. }
  39. void add(char c)
  40. {
  41. int noww = ++co;
  42. inits(noww);
  43. sam[noww].len = sam[last].len + 1;
  44. int p = last;
  45. while (p != -1 && !sam[p].sn[c - 'a'])
  46. {
  47. sam[p].sn[c - 'a'] = noww;
  48. p = sam[p].fail;
  49. }
  50. if (p == -1)
  51. {
  52. sam[noww].fail = 0;
  53. }
  54. else
  55. {
  56. int q = sam[p].sn[c - 'a'];
  57. if (sam[q].len == sam[p].len + 1)
  58. {
  59. sam[noww].fail = q;
  60. }
  61. else
  62. {
  63. int cp = ++co;
  64. sam[cp] = sam[q];
  65. sam[cp].len = sam[p].len + 1;
  66. // sam[cp].fl = 0;
  67. sam[q].fail = cp;
  68. sam[noww].fail = cp;
  69. while (p != -1 && sam[p].sn[c - 'a'] == q)
  70. {
  71. sam[p].sn[c - 'a'] = cp;
  72. p = sam[p].fail;
  73. }
  74. }
  75. }
  76. last = noww;
  77. update(noww);
  78. }
  79. int main()
  80. {
  81. while (scanf("%d%d%d", &n, &m, &k) == 3)
  82. {
  83. co = 0;
  84. last = 0;
  85. scanf("%s", ss);
  86. ans = 0;
  87. inits(0);
  88. for (int i = 0; ss[i]; ++i)
  89. {
  90. add(ss[i]);
  91. }
  92. for (int i = 1; i <= m; ++i)
  93. {
  94. int opt;
  95. scanf("%d", &opt);
  96. if (opt == 1)
  97. {
  98. char c[5];
  99. scanf("%s", c);
  100. add(c[0]);
  101. }
  102. else
  103. {
  104. printf("%lld\n", ans);
  105. }
  106. }
  107. }
  108. return 0;
  109. }

HDU 4641 K string 后缀自动机的更多相关文章

  1. HDU 4622 Reincarnation(后缀自动机)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=4622 [题目大意] 给出一个长度不超过2000的字符串,有不超过10000个询问,问[L,R]子串 ...

  2. HDU 4436 str2int(后缀自动机)(2012 Asia Tianjin Regional Contest)

    Problem Description In this problem, you are given several strings that contain only digits from '0' ...

  3. 【hihocoder#1413】Rikka with String 后缀自动机 + 差分

    搞了一上午+接近一下午这个题,然后被屠了个稀烂,默默仰慕一晚上学会SAM的以及半天4道SAM的hxy大爷. 题目链接:http://hihocoder.com/problemset/problem/1 ...

  4. 牛客多校第四场 I string 后缀自动机/回文自动机

    这个回文自动机的板有问题,它虽然能过这道题,但是在计算size的时候会出锅! 题意: 求一个字符串中本质不同的连续子串有几个,但是某串和它反转后的字符串算一个. 题解: 要注意的是,一般字符串题中的“ ...

  5. HDU 4436 str2int(后缀自动机)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=4436 [题目大意] 给出一些字符串,由0~9组成,求出所有不同子串的和. [题解] 将所有字符串添 ...

  6. HDU 4436 str2int (后缀自动机SAM,多串建立)

    str2int Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total S ...

  7. 识别子串 (string)——后缀自动机+线段树

    题目 [题目描述] 一般地,对于一个字符串 S,和 S 中第 $ i $ 个字符 x,定义子串 $ T=S(i.j) $ 为一个关于 x 的识别子申,当且仅当: 1.$ i \leq x \leq j ...

  8. Codeforces 917F Substrings in a String - 后缀自动机 - 分块 - bitset - KMP

    题目传送门 传送点I 传送点II 传送点III 题目大意 给定一个字母串,要求支持以下操作: 修改一个位置的字母 查询一段区间中,字符串$s$作为子串出现的次数 Solution 1 Bitset 每 ...

  9. cf1121F. Compress String(后缀自动机)

    题意 题目链接 Sol 居然出个SAM板子也是没谁了233 #include<bits/stdc++.h> #define Pair pair<int, int> #defin ...

  10. #1413 : Rikka with String 后缀自动机 + 二级差分

    http://hihocoder.com/problemset/problem/1413?sid=1199641 这题断断续续做了2个多星期吧,一直不会 设总答案为sum,替换后新加的子串数量为x,失 ...

随机推荐

  1. Go 语言开发环境搭建

    Go 语言开发环境搭建 目录 Go 语言开发环境搭建 一. GO 环境安装 1.1 下载 1.2 Go 版本的选择 1.3 安装 1.3.1 Windows安装 1.3.2 Linux下安装 1.3. ...

  2. ProcessingJS

    ProcessingJS 图形 rect(x, y, w, h)(在新窗口中打开) ellipse(x, y, w, h) triangle(x1, y1, x2, y2, x3, y3) line( ...

  3. Chiplet解决芯片技术发展瓶颈

    这是IC男奋斗史的第38篇原创 本文1776字,预计阅读4分钟. Chiplet封装是什么 介绍Chiplet前,先说下SOC.Chiplet和SOC是两个相互对立的概念,刚好可以用来互为参照. SO ...

  4. C/C++中的ACM题目输入处理——简单易上手

    这里就不按其他文章的以各种情况为分类方法,而是以方法本身为分类办法.因为有一些方法是不同情况通用的,比如已知数量数字的输入和未知数量数字的输入,其实可以用同一种办法. 输入 C/C++ :scanf正 ...

  5. mysql修改密码和开启远程访问

    mysql默认是关闭远程访问的,开启命令如下 1.首先打开mysql所在的bin目录,C:\Program Files\MySQL\MySQL Server 5.5\bin 在地址栏输入cmd,回车 ...

  6. log4j漏洞CVE-2021-44228复现-排雷篇

    一.环境搭建(用相同的环境才能保证一定成功) 下载vulhub,其他环境可能存在GET请求无效问题: git clone https://github.com/vulhub/vulhub.git 切换 ...

  7. Python 用户输入和字符串格式化指南

    Python 允许用户输入数据.这意味着我们可以向用户询问输入.在 Python 3.6 中,使用 input() 方法来获取用户输入.在 Python 2.7 中,使用 raw_input() 方法 ...

  8. JUC并发编程学习笔记(十七)彻底玩转单例模式

    彻底玩转单例模式 单例中最重要的思想------->构造器私有! 恶汉式.懒汉式(DCL懒汉式!) 恶汉式 package single; //饿汉式单例(问题:因为一上来就把对象加载了,所以可 ...

  9. Python 利用pandas和matplotlib绘制柱状折线图

    创建数据可视化图表:柱状图与折线图结合 在数据分析和展示中,经常需要将数据可视化呈现,以便更直观地理解数据背后的趋势和关联关系.本篇文章将介绍如何使用 Python 中的 Pandas 和 Matpl ...

  10. C/C++ extern “C“ 的问题

    声明 文章中的部分代码引用来在: https://blog.csdn.net/u012234115/article/details/43272441 场景 今天在CSDN中看到了一篇关于 extern ...