1. /*
  2. 首先答案显然是具有单调性的, 所以可以二分进行判断
  3. 然后当我们二分过后考虑dp来求最长匹配个数, 发现每个点能够转移的地点 肯定是一段区间, 然后这样就能够得到一个log^2算法
  4. 至于每个点的匹配最长区间, 我们可以预处理出所有地点的最长匹配串
  5. 然后发现这个东西可以进行单调栈优化, 原因是往后能往前最大匹配到的点是不会超过前面的, 否则前面那个也会更长
  6. 然后就能快乐地一个log了
  7. */
  8. #include<cstdio>
  9. #include<algorithm>
  10. #include<cstring>
  11. #include<queue>
  12. #include<iostream>
  13. #define ll long long
  14. #define M 2800010
  15. #define mmp make_pair
  16. using namespace std;
  17. int read() {
  18. int nm = 0, f = 1;
  19. char c = getchar();
  20. for(; !isdigit(c); c = getchar()) if(c == '-') f = -1;
  21. for(; isdigit(c); c = getchar()) nm = nm * 10 + c - '0';
  22. return nm * f;
  23. }
  24. char s[M];
  25. int ch[M][2], cnt = 1, lst = 1, fa[M], len[M], n, m;
  26. void insert(int c) {
  27. int p = ++cnt, f = lst;
  28. lst = p;
  29. len[p] = len[f] + 1;
  30. while(f && !ch[f][c]) ch[f][c] = p, f = fa[f];
  31. if(f == 0) {
  32. fa[p] = 1;
  33. } else {
  34. int q = ch[f][c];
  35. if(len[q] == len[f] + 1) {
  36. fa[p] = q;
  37. } else {
  38. int nq = ++cnt;
  39. memcpy(ch[nq], ch[q], sizeof(ch[q]));
  40. fa[nq] = fa[q];
  41. len[nq] = len[f] + 1;
  42. fa[p] = fa[q] = nq;
  43. while(f && ch[f][c] == q) ch[f][c] = nq, f = fa[f];
  44. }
  45. }
  46. }
  47. int q[M], h, t, pre[M], f[M];
  48. bool check(int k) {
  49. int l = strlen(s + 1);
  50. h = 1, t = 0;
  51. for(int i = 1; i <= l; i++) {
  52. f[i] = f[i - 1];
  53. if(i < k) continue;
  54. while(h <= t && f[q[t]] - q[t] <= f[i - k] - i + k) t--;
  55. q[++t] = i - k;
  56. while(h <= t && q[h] < i - pre[i]) h++;
  57. if(h <= t) f[i] = max(f[i], f[q[h]] + i - q[h]);
  58. }
  59. return f[l] * 10 >= l * 9;
  60. }
  61. void getpre() {
  62. int up = strlen(s + 1), now = 1, lenn = 0;
  63. for(int i = 1; i <= up; i++) {
  64. int c = s[i] - '0';
  65. while(now && !ch[now][c]) now = fa[now], lenn = len[now];
  66. if(!now) now = 1, lenn = 0;
  67. else now = ch[now][c], lenn++;
  68. pre[i] = lenn;
  69. }
  70. }
  71. int work() {
  72. getpre();
  73. int l = 1, r = strlen(s + 1);
  74. while(l + 1 < r) {
  75. int mid = (l + r) >> 1;
  76. if(check(mid)) l = mid;
  77. else r = mid;
  78. }
  79. if(!check(l)) return -1;
  80. if(check(r)) return r;
  81. return l;
  82. }
  83. int main() {
  84. n = read(), m = read();
  85. for(int i = 1; i <= m; i++) {
  86. lst = 1;
  87. scanf("%s", s + 1);
  88. int l = strlen(s + 1);
  89. for(int j = 1; j <= l; j++) insert(s[j] - '0');
  90. }
  91. while(n--) {
  92. scanf("%s", s + 1);
  93. cout << work() << "\n";
  94. }
  95. return 0;
  96. }

[CTSC2012]熟悉的文章 (后缀自动机 单调队列)的更多相关文章

  1. [CTSC2012]熟悉的文章(后缀自动机+动态规划)

    题目描述 阿米巴是小强的好朋友. 在小强眼中,阿米巴是一个作文成绩很高的文艺青年.为了获取考试作文的真谛,小强向阿米巴求教.阿米巴给小强展示了几篇作文,小强觉得这些文章怎么看怎么觉得熟悉,仿佛是某些范 ...

  2. [CTSC2012]熟悉的文章 后缀自动机

    题面:洛谷 题解: 观察到L是可二分的,因此我们二分L,然后就只需要想办法判断这个L是否可行即可. 因为要尽量使L可行,因此我们需要求出对于给定L,这个串最多能匹配上多少字符. 如果我们可以对每个位置 ...

  3. 【BZOJ2806】【CTSC2012】Cheat - 广义后缀自动机+单调队列优化DP

    题意: Description Input 第一行两个整数N,M表示待检查的作文数量,和小强的标准作文库的行数 接下来M行的01串,表示标准作文库 接下来N行的01串,表示N篇作文 Output N行 ...

  4. BZOJ 2806: [Ctsc2012]Cheat [广义后缀自动机 单调队列优化DP 二分]

    2806: [Ctsc2012]Cheat 题意: 多个主串和多个询问串,每次询问将询问串分成多个连续子串,如果一个子串长度>=L且在主串中出现过就是熟悉的 如果熟悉的字符串长度>=询问串 ...

  5. bzoj 2806 [Ctsc2012]Cheat——广义后缀自动机+单调队列优化DP

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2806 只想着怎么用后缀数据结构做,其实应该考虑结合其他算法. 可以二分那个长度 L .设当前 ...

  6. BZOJ 2806 [Ctsc2012]Cheat ——后缀自动机 单调队列优化DP

    先建出广义后缀自动机. 然后跑出文章中每一个位置的最大匹配距离. 然后定义$f[i]$表示匹配到以$i$结尾的串时,最长的匹配距离. 显然可以二分$L$的取值. 然后容易得到$DP$方程 $f[i]= ...

  7. 【BZOJ2806】Cheat 【广义后缀自动机+单调队列优化dp+二分】

    题意 有M篇标准作文组成了一个作文库(每篇作文都是一个01的字符串),然后给出N篇作文(自然也是01字符串).如果一个长度不小于L的串在作文库中出现过,那么它是熟悉的.对于某一篇作文,我们要把它分为若 ...

  8. P4022 [CTSC2012]熟悉的文章

    题目 P4022 [CTSC2012]熟悉的文章 题目大意:多个文本串,多个匹配串,我们求\(L\),\(L\)指(匹配串中\(≥L\)长度的子串出现在文本串才为"熟悉",使得匹配 ...

  9. [CTSC2012]熟悉的文章(广义后缀自动机+二分答案+单调队列优化DP)

    我们对作文库建出广义后缀自动机.考虑用\(SAM\)处理出来一个数组\(mx[i]\),表示从作文的第\(i\)个位置向左最远在作文库中出现的子串的长度.这个东西可以在\(SAM\)上跑\(trans ...

随机推荐

  1. taro 事件处理

    https://nervjs.github.io/taro/docs/event.html Taro 元素的事件处理和 DOM 元素的很相似.但是有一点语法上的不同: Taro 事件绑定属性的命名采用 ...

  2. Linux基础入门之vsFTP+MySQL/MariaDB认证实现虚拟用户配置详解

    https://www.dwhd.org/20150603_144841.html 摘要 VSFTP可以使用系统账户或者匿名账户登录,但是出于安全的考虑,通常建议使用vsftp虚拟账户来登录ftp服务 ...

  3. js 控件样式显隐和赋值

    控制样式显示: $("#againMetting")[0].style.display = "inline";//显示 $("#againMettin ...

  4. 关键字:this、ref、out

    Class1.cs using System; using System.Collections.Generic; using System.Linq; using System.Text; usin ...

  5. str.replace()和re.sub()/calendar.month_abbr/re.subn()/upper和lower和capitalize/贪婪匹配和费贪婪匹配/re.S和re.DOTALL 笔记

    str.replace()可以进行简单的替换 >>> a = 'one.txt, index.py, index.php, index.html, index.js' >> ...

  6. linux项目部署常用命令

    原文出处:http://blog.csdn.net/u013628152/article/details/45847013 1:执行命令#find / -name tomcat,系统将列出所有tomc ...

  7. Device Identifier and Device DNA初识

    Device Identifier and Device DNA初识 信息来源 怎么样去用这个DNA:

  8. oracle--合并行数据(拼接字符串),获取查询数据的前3条数据...

    --标准函数Lpad 可以实现左补零,但是如果多于需要长度,则会截断字符串 SELECT LPAD ('1' , 3 , '0') FROM DUAL -- return 001 情况一:需要补零.  ...

  9. Windows右键菜单中新建项目添加与删除

    一种是如  txt 类型: HKEY_CLASSES_ROOT\.txt\ShellNew 项下空字符串值:NullFile 另一种如MsOffice类型: HKEY_CLASSES_ROOT\.xl ...

  10. 黄聪:Pjax 无刷新开发web,更好用户体验

    什么Ajax.Pjax.Njax...神马玩意? 有Njax吗? 木有...不过真有Pjax!! 其实pjax就是用到了html5的新history api: pushState和replaceSta ...