http://www.spoj.com/problems/LCS2/

这道题想了好久。

做法是对第一个串建后缀自动机,然后用后面的串去匹配它,并在走过的状态上记录走到这个状态时的最长距离。每匹配完一个串要对每个状态往它的parent更新,因为状态记录的最长距离一定大于parent的val值,所以parent的最长距离直接赋为val即可。

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. using namespace std;
  5. struct State {
  6. State *par, *go[26];
  7. int val, mn, now;
  8. } *root, *last, pool[250003], *id[250003];
  9. int tot = 0;
  10. State *newState(int _val) {
  11. State *t = &pool[++tot];
  12. t->par = 0; t->val = t->now = 0;
  13. memset(t->go, 0, sizeof(t->go));
  14. t->mn = t->val = _val;
  15. return t;
  16. }
  17. void extend(int w) {
  18. State *p = last;
  19. State *np = newState(p->val + 1);
  20. while (p && p->go[w] == 0)
  21. p->go[w] = np, p = p->par;
  22. if (p == 0) np->par = root;
  23. else {
  24. State *q = p->go[w];
  25. if (q->val == p->val + 1) np->par = q;
  26. else {
  27. State *nq = newState(p->val + 1);
  28. memcpy(nq->go, q->go, sizeof(q->go));
  29. nq->par = q->par;
  30. q->par = np->par = nq;
  31. while (p && p->go[w] == q)
  32. p->go[w] = nq, p = p->par;
  33. }
  34. }
  35. last = np;
  36. }
  37. int len, c[100003];
  38. char s[100003];
  39. int main() {
  40. root = last = newState(0);
  41. scanf("%s", s + 1);
  42. len = strlen(s + 1);
  43. for(int i = 1; i <= len; ++i)
  44. extend(s[i] - 'a');
  45. for(int i = 1; i <= tot; ++i)
  46. ++c[pool[i].val];
  47. for(int i = 1; i <= len; ++i)
  48. c[i] += c[i - 1];
  49. for(int i = tot; i >= 1; --i)
  50. id[c[pool[i].val]--] = &pool[i];
  51. State *tmp; int now, x;
  52. while (~scanf("%s", s + 1)) {
  53. len = strlen(s + 1);
  54. tmp = root; now = 0;
  55. for(int i = 1; i <= len; ++i) {
  56. x = s[i] - 'a';
  57. if (tmp->go[x]) {
  58. tmp = tmp->go[x];
  59. ++now;
  60. } else {
  61. while (tmp && tmp->go[x] == 0)
  62. tmp = tmp->par;
  63. if (tmp == 0) tmp = root, now = 0;
  64. else now = tmp->val + 1, tmp = tmp->go[x];
  65. }
  66. tmp->now = max(tmp->now, now);
  67. }
  68. for(int i = tot; i >= 1; --i) {
  69. tmp = id[i];
  70. tmp->mn = min(tmp->mn, tmp->now);
  71. if (tmp->par != 0 && tmp->now != 0) tmp->par->now = tmp->par->val;
  72. tmp->now = 0;
  73. }
  74. }
  75. int ans = 0;
  76. for(int i = 1; i <= tot; ++i)
  77. ans = max(ans, pool[i].mn);
  78. printf("%d\n", ans);
  79. return 0;
  80. }

【SPOJ 1812】Longest Common Substring II的更多相关文章

  1. 【spoj LCS2】 Longest Common Substring II

    http://www.spoj.com/problems/LCS2/ (题目链接) 题意 求多个串的最长公共子串 Solution 对其中一个串构造后缀自动机,然后其它串在上面跑匹配.对于每个串都可以 ...

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

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

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

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

  4. 【刷题】SPOJ 1812 LCS2 - Longest Common Substring II

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

  5. SPOJ 1812 LCS2 - Longest Common Substring II

    思路 后缀自动机求多串的最长公共子串 对第一个建出后缀自动机,其他的在SAM上匹配,更新到一个节点的匹配长度最大值即可,最后对所有最大值取min得到一个节点的答案,对所有节点答案求max即可 然后注意 ...

  6. SPOJ 1812 LCS2 - Longest Common Substring II (后缀自动机、状压DP)

    手动博客搬家: 本文发表于20181217 23:54:35, 原地址https://blog.csdn.net/suncongbo/article/details/85058680 人生第一道后缀自 ...

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

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

  8. 【SPOJ】Longest Common Substring II

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

  9. 【hdu 1403】Longest Common Substring

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

随机推荐

  1. 北理工c语言期末考试

    1 给定一个区间,输出其中前半部分数字之和等于后半部分数字之和的数,没有则输出No output.(15分) 题目内容: 给定一个区间,输出其中前半部分数字之和等于后半部分数字之和的数,没有则输出No ...

  2. Codeforces 549C. The Game Of Parity[博弈论]

    C. The Game Of Parity time limit per test 1 second memory limit per test 256 megabytes input standar ...

  3. VS Code

    VS Code VS Code(Visual Studio Code)是由微软研发的一款免费.开源的跨平台文本(代码)编辑器.几乎完美的编辑器. 官网:https://code.visualstudi ...

  4. 菜鸟的IT生活4

    今天主要复习了以前的内容,输入输出,数据类型,运算符,顺序语句,分支语句等等,把几个不太连贯跟没上传过的传一下,以后加深下印象,加油!

  5. Mantis1.2.19 在Windows 平台上的安装配置详解

    安装环境: WindowsXP 32 Apache2.2.22+PHP5.4.39+MySQL5.5.28 一.简介 MantisBT是由PHP开发的.基于WEB的缺陷跟踪系统,并采用开源数据库MyS ...

  6. 如何在Kali Linux下编译Windows Exploit

    前言 微软的Windows在企业或是个人应用领域占据着最大的市场份额,在渗透测试过程中你会经常遇到很多Windows的工作站和服务器.另一方面,大多数渗透测试人员主要使用基于Linux的发行版渗透测试 ...

  7. poj 3468

    A Simple Problem with Integers Time Limit: 5000MS Memory Limit: 131072K Total Submissions: 90736 Acc ...

  8. fragment的切换(解决REPLACE的低效)

    在项目中切换Fragment,一直都是用replace()方法来替换Fragment.但是这样做有一个问题,每次切换的时候Fragment都会重新实列化,重新加载一次数据,这样做会非常消耗性能用用户的 ...

  9. PPT文档页数显示的增加和更新

    在PPT的右下角增加页数的显示能够帮助演讲者把握进度,所以会经常遇到需要把页数显示在右下角的情况,这次在制作ppt的时候也遇到了.因此在这里总结一下设置方法. 一.在右下角显示当前页数和总页数 1)获 ...

  10. NSArray遍历和修改崩溃

    //一.代码 NSArray *array = [self.dataList mutableCopy]; 或 NSArray *array = [NSArray arrayWithArray:self ...