Longest Common Substring

\[Time Limit: 294ms \quad Memory Limit: 1572864 kB
\]

题意

给出两个串,求两个串的最长公共连续子序列的长度,两个串的长度小于等于250000。

思路

先对第一个串构建后缀自动机,根据后缀自动机的性质,从 \(root\) 的所有路径都是原串中的子串,又因为构建的时候,我们用 \(node[i].len\) 表示与节点 \(i\) 的 \(endpos\) 相同的所有子串集合的最长长度,那么我们就可以在后缀自动机上一次添加一个字符的去查询 \(res\) ,然后最大的 \(res\) 就是最后的答案。

在后缀自动机上查询的时候,我们用两个变量来更新答案,\(p\) 表示现在在后缀自动机上的状态,\(res\) 表示目前的最长公共连续长度。

  • 如果对于下一个字符 \(k\) ,现在的 \(p\) 有这样的一条边,那么直接更新 \(p\),并且 \(res\)++。
  • 如果没有这样的一条边,那么就从 \(p\) 跳到 \(node[i].fa\) 的位置,一直跳到有 \(k\) 的一条边为止停下或者走完整个后缀自动机。
  • 如果跳到结束也没有找到 \(k\) 边,那么就让 \(p\) 变回 \(root\),\(res=0\)。
  1. #include <map>
  2. #include <set>
  3. #include <list>
  4. #include <ctime>
  5. #include <cmath>
  6. #include <stack>
  7. #include <queue>
  8. #include <cfloat>
  9. #include <string>
  10. #include <vector>
  11. #include <cstdio>
  12. #include <bitset>
  13. #include <cstdlib>
  14. #include <cstring>
  15. #include <iostream>
  16. #include <algorithm>
  17. #define lowbit(x) x & (-x)
  18. #define mes(a, b) memset(a, b, sizeof a)
  19. #define fi first
  20. #define se second
  21. #define pii pair<int, int>
  22. #define INOPEN freopen("in.txt", "r", stdin)
  23. #define OUTOPEN freopen("out.txt", "w", stdout)
  24. typedef unsigned long long int ull;
  25. typedef long long int ll;
  26. const int maxn = 3e5 + 10;
  27. const int maxm = 1e5 + 10;
  28. const ll mod = 1e9 + 7;
  29. const ll INF = 1e18 + 100;
  30. const int inf = 0x3f3f3f3f;
  31. const double pi = acos(-1.0);
  32. const double eps = 1e-8;
  33. using namespace std;
  34. int n, m;
  35. int cas, tol, T;
  36. struct SAM {
  37. struct Node{
  38. int next[27];
  39. int fa, len;
  40. void init() {
  41. mes(next, 0);
  42. fa = len = 0;
  43. }
  44. } node[maxn<<1];
  45. int sz, last;
  46. void init() {
  47. sz = last = 1;
  48. node[sz].init();
  49. }
  50. void insert(int k) {
  51. int p = last, np = last = ++sz;
  52. node[np].init();
  53. node[np].len = node[p].len+1;
  54. for(; p && !node[p].next[k]; p=node[p].fa)
  55. node[p].next[k] = np;
  56. if(p==0) {
  57. node[np].fa = 1;
  58. } else {
  59. int q = node[p].next[k];
  60. if(node[q].len == node[p].len + 1) {
  61. node[np].fa = q;
  62. } else {
  63. int nq = ++sz;
  64. node[nq] = node[q];
  65. node[nq].len = node[p].len+1;
  66. node[np].fa = node[q].fa = nq;
  67. for(; p&&node[p].next[k]==q; p=node[p].fa)
  68. node[p].next[k] = nq;
  69. }
  70. }
  71. }
  72. int solve(char *s) {
  73. int len = strlen(s+1);
  74. int res = 0, p = 1, ans = 0;
  75. for(int i=1; i<=len; i++) {
  76. int k = s[i]-'a'+1;
  77. while(p && !node[p].next[k]) {
  78. p = node[p].fa;
  79. res = node[p].len;
  80. }
  81. if(!p) {
  82. p = 1;
  83. res = 0;
  84. } else {
  85. p = node[p].next[k];
  86. res++;
  87. }
  88. ans = max(ans, res);
  89. }
  90. return ans;
  91. }
  92. } sam;
  93. char s[maxn], t[maxn];
  94. int main() {
  95. scanf("%s%s", s+1, t+1);
  96. sam.init();
  97. int len = strlen(s+1);
  98. for(int i=1; i<=len; i++) {
  99. sam.insert(s[i]-'a'+1);
  100. }
  101. int ans = sam.solve(t);
  102. printf("%d\n", ans);
  103. return 0;
  104. }

Longest Common Substring SPOJ - LCS (后缀自动机)的更多相关文章

  1. 【SPOJ】Longest Common Substring II (后缀自动机)

    [SPOJ]Longest Common Substring II (后缀自动机) 题面 Vjudge 题意:求若干个串的最长公共子串 题解 对于某一个串构建\(SAM\) 每个串依次进行匹配 同时记 ...

  2. SPOJ 1812 Longest Common Substring II(后缀自动机)(LCS2)

    A string is finite sequence of characters over a non-empty finite set Σ. In this problem, Σ is the s ...

  3. LCS - Longest Common Substring(spoj1811) (sam(后缀自动机)+LCS)

    A string is finite sequence of characters over a non-empty finite set \(\sum\). In this problem, \(\ ...

  4. 【SPOJ】1812. Longest Common Substring II(后缀自动机)

    http://www.spoj.com/problems/LCS2/ 发现了我原来对sam的理解的一个坑233 本题容易看出就是将所有匹配长度记录在状态上然后取min后再对所有状态取max. 但是不要 ...

  5. SPOJ 1812 Longest Common Substring II(后缀自动机)

    [题目链接] http://www.spoj.com/problems/LCS2/ [题目大意] 求n个串的最长公共子串 [题解] 对一个串建立后缀自动机,剩余的串在上面跑,保存匹配每个状态的最小值, ...

  6. SPOJ - LCS2 Longest Common Substring II(后缀自动机)题解

    题意: 求\(n\)个串的最大\(LCS\). 思路: 把第一个串建后缀自动机,然后枚举所有串.对于每个串,求出这个串在\(i\)节点的最大匹配为\(temp[i]\)(当前串在这个节点最多取多少), ...

  7. 2018.12.15 spoj Longest Common Substring II(后缀自动机)

    传送门 后缀自动机基础题. 给出10个串求最长公共子串. 我们对其中一个建一个samsamsam,然后用剩下九个去更新范围即可. 代码: #include<bits/stdc++.h> # ...

  8. SPOJ 1811. Longest Common Substring (LCS,两个字符串的最长公共子串, 后缀自动机SAM)

    1811. Longest Common Substring Problem code: LCS A string is finite sequence of characters over a no ...

  9. SPOJ - LCS 后缀自动机入门

    LCS - Longest Common Substring A string is finite sequence of characters over a non-empty finite set ...

随机推荐

  1. maven 引入qrcode.jar

        mvn install:install-file -Dfile=e:\QRCode.jar -DgroupId=QRCode -DartifactId=QRCode -Dversion=3.0 ...

  2. Java基础知识点总结(一)

    1.源文件声明规则2.JAVA基本类型void3.数据类型默认值4.自动类型转换5.Java变量类型6.Java局部变量7.访问控制修饰符8.父类与子类的访问控制9.instanceof运算符 1.源 ...

  3. excel 使用

    列于列拼接

  4. 【题解】【网络流24题】汽车加油行驶问题 [P4009] [Loj6223]

    [题解][网络流24题]汽车加油行驶问题 [P4009] [Loj6223] 传送门:汽车加油行驶问题 \([P4009]\) \([Loj6223]\) [题目描述] 给出一个 \(N \times ...

  5. java学习:循环结构的使用规则和注意事项

    循环结构的基本组成部分,一般可分为四部分: 初始化语句:在循环开始最初执行,而且只做唯一一次 条件判断:如果成立,则循环继续:如果不成立,则循环退出. 循环体:重复要做的事情内容,若干行语句. 进步语 ...

  6. PriorityQueue详解

    美人如斯!好好看文章! 前言 java中关于Queue队列的实现繁多(关于Queue可以移步至我的另一篇文章:<Queue介绍>),每种实现根据自身的特性都有相应的应用场景.这里我们就来聊 ...

  7. TeamViewer14试用版到期-怎么解决

    Teamviewer14提示试用期已到期怎么办? 问题分析: 出现这种问题,是因为在安装是选择了[公司/商务用途]或者[以上都是]这两个选项中的一个 解决方法: 1.退出TeamViewer远程软件, ...

  8. vim中常用折叠命令

    最常用3个折叠命令 .反复打开关闭折叠:za (意思就是,当光标处折叠处于打开状态,za关闭之,当光标处折叠关闭状态,打开之) .打开全部折叠:zR .关闭全部折叠:zM 小试折叠: :set fdm ...

  9. CentOS 7 安装 mysql 5.7.27 for zabbix

    本文是因为需要安装zabbix系统,才贴出的此步骤,供自己查阅方便之用: 在安装使用zabbix前,需要先安装数据库,这里使用的是MySQL数据库进行部署,给出安装步骤,大家觉得有用也可收藏: 当然安 ...

  10. javascript 对象之hasOwnProperty()方法

    hasOwnProperty()方法是判断某一个对象是否有你给出的属性名称,需要注意的是该方法无法检测该对象原型连中是否具有该属性 具体格式下: var person = {"name&qu ...