http://www.spoj.com/problems/LCS2/ (题目链接)

题意

  求多个串的最长公共子串

Solution

  对其中一个串构造后缀自动机,然后其它串在上面跑匹配。对于每个串都可以跑出在SAM上的每一个节点的最长公共子串的长度,当然,有些节点虽然匹配时可能没有经过,但是在parent树上它的儿子却被经过了,作为儿子的后缀,那么这些节点显然也是被经过的,所以我们需要用parent树上的儿子节点去更新其父亲节点。完成之后,我们再对全局的匹配长度进行更新(取min)。

  爱神:对于SAM初学,要深刻理解出现次数向父亲传递,接收串数从儿子获取这句话。这里的父亲是parent树上的父亲,儿子是SAM图上的后继节点。

代码

  1. // spoj LCS2
  2. #include<algorithm>
  3. #include<iostream>
  4. #include<cstdlib>
  5. #include<cstring>
  6. #include<vector>
  7. #include<cstdio>
  8. #include<cmath>
  9. #include<set>
  10. #define LL long long
  11. #define inf 1<<30
  12. #define Pi acos(-1.0)
  13. #define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
  14. using namespace std;
  15.  
  16. const int maxn=100010;
  17. char s[maxn];
  18.  
  19. namespace SAM {
  20. int Dargen,sz,last,n;
  21. int par[maxn<<1],len[maxn<<1],ch[maxn<<1][26],mat[maxn<<1],f[maxn<<1];
  22. int b[maxn],id[maxn<<1];
  23. void Extend(int c) {
  24. int np=++sz,p=last;last=np;
  25. len[np]=len[p]+1;
  26. for (;p && !ch[p][c];p=par[p]) ch[p][c]=np;
  27. if (!p) par[np]=Dargen;
  28. else {
  29. int q=ch[p][c];
  30. if (len[q]==len[p]+1) par[np]=q;
  31. else {
  32. int nq=++sz;len[nq]=len[p]+1;
  33. memcpy(ch[nq],ch[q],sizeof(ch[q]));
  34. par[nq]=par[q];
  35. par[np]=par[q]=nq;
  36. for (;p && ch[p][c]==q;p=par[p]) ch[p][c]=nq;
  37. }
  38. }
  39. }
  40. void build() {
  41. last=sz=Dargen=1;
  42. n=strlen(s+1);
  43. for (int i=1;i<=n;i++) Extend(s[i]-'a');
  44. }
  45. void pre() {
  46. for (int i=1;i<=sz;i++) b[len[i]]++;
  47. for (int i=1;i<=n;i++) b[i]+=b[i-1];
  48. for (int i=1;i<=sz;i++) id[b[len[i]]--]=i;
  49. for (int i=1;i<=sz;i++) mat[i]=inf;
  50. }
  51. void match() {
  52. int n=strlen(s+1);
  53. int ll=0;
  54. for (int i=1;i<=sz;i++) f[i]=0;
  55. for (int p=Dargen,i=1;i<=n;i++) {
  56. while (p>1 && !ch[p][s[i]-'a']) p=par[p],ll=len[p];
  57. if (ch[p][s[i]-'a']) {
  58. p=ch[p][s[i]-'a'];
  59. f[p]=max(f[p],++ll);
  60. }
  61. }
  62. for (int i=sz;i>=1;i--)
  63. if (f[id[i]]) f[par[id[i]]]=len[par[id[i]]];
  64. for (int i=1;i<=sz;i++) mat[i]=min(mat[i],f[i]);
  65. }
  66. int query() {
  67. int ans=0;
  68. for (int i=1;i<=sz;i++) ans=max(ans,mat[i]);
  69. return ans;
  70. }
  71. }
  72. using namespace SAM;
  73.  
  74. int main() {
  75. scanf("%s",s+1);
  76. build();
  77. pre();
  78. while (scanf("%s",s+1)!=EOF) match();
  79. printf("%d",query());
  80. return 0;
  81. }

【spoj LCS2】 Longest Common Substring II的更多相关文章

  1. 【SPOJ - LCS2】Longest Common Substring II【SAM】

    题意 求出多个串的最长公共子串. 分析 刚学SAM想做这个题的话最好先去做一下那道codevs3160.求两个串的LCS应该怎么求?把一个串s1建自动机,然后跑另一个串s2,然后找出s2每个前缀的最长 ...

  2. 【SPOJ 1812】Longest Common Substring II

    http://www.spoj.com/problems/LCS2/ 这道题想了好久. 做法是对第一个串建后缀自动机,然后用后面的串去匹配它,并在走过的状态上记录走到这个状态时的最长距离.每匹配完一个 ...

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

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

  4. 【SPOJ】Longest Common Substring II

    [SPOJ]Longest Common Substring II 多个字符串求最长公共子串 还是将一个子串建SAM,其他字符串全部跑一边,记录每个点的最大贡献 由于是所有串,要对每个点每个字符串跑完 ...

  5. 【hdu 1403】Longest Common Substring

    [链接]h在这里写链接 [题意] 求两个串的最长公共子串. [题解] Sa[i]表示的是字典序为i的后缀的起始位置. 可以把两个字符串合在一起(中间用一个比'z'大的字符分割); 则如果Sa[i-1] ...

  6. 【SP1812】LCS2 - Longest Common Substring II

    [SP1812]LCS2 - Longest Common Substring II 题面 洛谷 题解 你首先得会做这题. 然后就其实就很简单了, 你在每一个状态\(i\)打一个标记\(f[i]\)表 ...

  7. SPOJ1812 LCS2 - Longest Common Substring II【SAM LCS】

    LCS2 - Longest Common Substring II 多个字符串找最长公共子串 以其中一个串建\(SAM\),然后用其他串一个个去匹配,每次的匹配方式和两个串找\(LCS\)一样,就是 ...

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

    [SPOJ]Longest Common Substring(后缀自动机) 题面 Vjudge 题意:求两个串的最长公共子串 题解 \(SA\)的做法很简单 不再赘述 对于一个串构建\(SAM\) 另 ...

  9. spoj 1812 LCS2 - Longest Common Substring II (后缀自己主动机)

    spoj 1812 LCS2 - Longest Common Substring II 题意: 给出最多n个字符串A[1], ..., A[n], 求这n个字符串的最长公共子串. 限制: 1 < ...

随机推荐

  1. POJ1611 The Suspects 并查集模板题

    题目大意:中文题不多说了 题目思路:将每一个可能患病的人纳入同一个集合,然后遍历查找每个点,如果改点点的根节点和0号学生的根节点相同,则该点可能是病人. 模板题并没有思路上的困难,只不过在遍历时需要额 ...

  2. ZOJ3944People Counting<暴力/枚举>

    题意:输入一张照片,给出人物的特征,判断有多少个人. .O. /|\ (.) 思路:按照3*3的图统计,只要有一个点符合就加1 #include<cstdio> #include<i ...

  3. 块和内嵌总结,以及各个标签的应用。其中的ul ol dl特殊定义为auto,使得里面的内容展开

    <!doctype html> <html> <head> <meta charset="UTF-8"/> <title> ...

  4. js中的全局函数

    以前没搞懂JS的全局函数,全局函数和window对象的函数不一样.全局函数不属于任何一个内置对象. JS包含以下7个全局函数,用于一些常用的功能:escape(),eval(),isNan(),isF ...

  5. AOP 在javascript 中的使用

    AOP(Aspect Oriented Programming) 意为面向切面编程 可以在不修改原有代码的情况下增加新功能,利用AOP可以对业务逻辑各个部分进行隔离,从而使得业务逻辑各部分的耦合度降低 ...

  6. 【HighCharts系列教程】十、图例属性——legend

    一.legend属性说明 Legend是HighCharts图表的图例属性,如图 默认情况下,HighCharts都会有图例,无特殊情况,默认即可满足需求,所以一般不用配置Legend属性. 二.la ...

  7. iOS系统弃用方法更新方法

    -boundingRectWithSize:options:attributes:context:用法 - (CGSize)sizeWithFont:(UIFont *)font constraine ...

  8. Bootstrap的文档大概介绍

    1.预置CSS样式 (1)Normalize.css  增强浏览器表现的一致性. (2)布局容器——版芯:container. ①.container 类用于固定宽度并支持响应式布局的容器.     ...

  9. x86_64是什么意思

    x86指的是32位计算机的架构,也指32位的操作系统,比如i386,i686,i486等:x86_64和x64指的都是64位架构,也指64位操作系统

  10. 微信小程序一些简单的快捷键

    常用快捷键 格式调整 Ctrl+S:保存文件Ctrl+[, Ctrl+]:代码行缩进Ctrl+Shift+[, Ctrl+Shift+]:折叠打开代码块Ctrl+C Ctrl+V:复制粘贴,如果没有选 ...