多串的LCS,注意要利用拓扑序更新suf的len。

我用min,max,三目会超时,所以都改成了if,else

  1. #pragma warning(disable:4996)
  2. #include<cstring>
  3. #include<string>
  4. #include<iostream>
  5. #include<cmath>
  6. #include<vector>
  7. #include<algorithm>
  8. #define maxn 100050
  9. using namespace std;
  10.  
  11. struct State{
  12. State *suf, *go[26];
  13. int val, len[2];
  14. State() :suf(0), val(0){
  15. memset(go, 0, sizeof(go));
  16. memset(len, 0, sizeof(len));
  17. }
  18. }*root, *last;
  19.  
  20. State statePool[maxn * 2], *cur;
  21.  
  22. void init()
  23. {
  24. cur = statePool;
  25. root = last = cur++;
  26. }
  27.  
  28. void extend(int w)
  29. {
  30. State *p = last, *np = cur++;
  31. np->val = p->val + 1;
  32. np->len[1] = np->val;
  33. while (p&&!p->go[w]) p->go[w] = np, p = p->suf;
  34. if (!p) np->suf = root;
  35. else{
  36. State *q = p->go[w];
  37. if (p->val + 1 == q->val){
  38. np->suf = q;
  39. }
  40. else{
  41. State *nq = cur++;
  42. memcpy(nq->go, q->go, sizeof q->go);
  43. nq->val = p->val + 1;
  44. nq->len[1] = nq->val;
  45. nq->suf = q->suf;
  46. q->suf = nq;
  47. np->suf = nq;
  48. while (p&&p->go[w] == q){
  49. p->go[w] = nq, p = p->suf;
  50. }
  51. }
  52. }
  53. last = np;
  54. }
  55.  
  56. char str[maxn];
  57. int n;
  58.  
  59. int bcnt[maxn];
  60. State *b[maxn * 2];
  61.  
  62. int main()
  63. {
  64. n = 0;
  65. scanf("%s", str);
  66. init();
  67. int len = strlen(str);
  68. for (int i = 0; i < len; i++){
  69. extend(str[i] - 'a');
  70. }
  71. int tot = cur - root;
  72. memset(bcnt, 0, sizeof(bcnt));
  73. for (int i = 0; i < tot; i++) bcnt[statePool[i].val]++;
  74. for (int i = 1; i <= len; i++) bcnt[i] += bcnt[i - 1];
  75. for (int i = tot - 1; i >= 0; i--) b[--bcnt[statePool[i].val]] = &statePool[i];
  76. while (scanf("%s", str) != EOF){
  77. int lenb = strlen(str);
  78. int cnt = 0;
  79. State *p = root;
  80. for (int i = 0; i < lenb; i++){
  81. if (p->go[str[i] - 'a']){
  82. cnt++;
  83. p = p->go[str[i] - 'a'];
  84. }
  85. else{
  86. while (p&&!p->go[str[i] - 'a']) p = p->suf;
  87. if (!p) {
  88. p = root;
  89. cnt = 0;
  90. }
  91. else{
  92. cnt = p->val + 1;
  93. p = p->go[str[i] - 'a'];
  94. }
  95. }
  96. if (cnt > p->len[0]){
  97. p->len[0] = cnt;
  98. }
  99. }
  100. for (int i = tot - 1; i >= 0; i--){
  101. if (b[i]->len[0]<b[i]->len[1]) b[i]->len[1] = b[i]->len[0];
  102. if (b[i]->suf&&b[i]->suf->len[0]< b[i]->len[0]){
  103. b[i]->suf->len[0] = b[i]->len[0];
  104. }
  105. b[i]->len[0] = 0;
  106. }
  107. }
  108. int ans = 0;
  109. for (int i = 0; i < tot; i++){
  110. if (ans < b[i]->len[1]){
  111. ans = b[i]->len[1];
  112. }
  113. }
  114. printf("%d\n", ans);
  115. return 0;
  116. }

SPOJ LCS2 后缀自动机的更多相关文章

  1. 多个串的最长公共子串 SPOJ - LCS2 后缀自动机

    题意: 求多个串的最长公共子串 这里用的是O(n)的后缀自动机写法 我后缀数组的专题有nlog(n)写法的 题解: 对于其中的一个串建立后缀自动机 然后对于后缀自动机上面的每一个节点求出每一个节点最长 ...

  2. SPOJ NSUBSTR (后缀自动机)

    SPOJ NSUBSTR Problem : 给一个长度为n的字符串,要求分别输出长度为1~n的子串的最多出现次数. Solution :首先对字符串建立后缀自动机,在根据fail指针建立出后缀树,对 ...

  3. SPOJ LCS 后缀自动机

    用后缀自动机求两个长串的最长公共子串,效果拔群.多样例的时候memset要去掉. 解题思路就是跟CLJ的一模一样啦. #pragma warning(disable:4996) #include< ...

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

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

  5. SPOJ LCS 后缀自动机找最大公共子串

    这里用第一个字符串构建完成后缀自动机以后 不断用第二个字符串从左往右沿着后缀自动机往前走,如能找到,那么当前匹配配数加1 如果找不到,那么就不断沿着后缀树不断往前找到所能匹配到当前字符的最大长度,然后 ...

  6. SPOJ 7258 (后缀自动机)

    转载:http://hzwer.com/4492.html 给一个长度不超过90000的串S,每次询问它的所有不同子串中,字典序第K小的,询问不超过500个. 搞出后缀自动机 dp处理出每个点往下走能 ...

  7. 长度为x的本质不同的串的出现次数 SPOJ - NSUBSTR 后缀自动机简单应用

    题意: 长度为x的本质不同的串的出现次数 题解: 先处理出每一个节点所对应的子串出现的次数 然后取max就好了 #include <set> #include <map> #i ...

  8. SPOJ.1812.LCS2(后缀自动机)

    题目链接 \(Description\) 求最多10个串的LCS(最长公共子序列). \(Solution\) 类比上题,对一个串建SAM,我们可以逐串地求出其在每个节点所能匹配的最大长度mx[i]. ...

  9. SPOJ 1812 LCS2 [后缀自动机 DP]

    题意: 求多个串<=10的最长连续子串 一个串建SAM,然后其他串在上面走 每个状态记录所有串在这个状态的公共子串的最小值 一个串在上面走的时候记录与每个状态公共子串的最大值,注意出现次数向父亲 ...

随机推荐

  1. Linux多线程编程(不限Linux)

    前言 线程?为什么有了进程还需要线程呢,他们有什么区别?使用线程有什么优势呢?还有多线程编程的一些细节问题,如线程之间怎样同步.互斥,这些东西将在本文中介绍.我在某QQ群里见到这样一道面试题: 是否熟 ...

  2. 链表的创建、测长、排序、插入、逆序的实现(C语言)

    #include <stdio.h> #define END_elem 0 struct node { int date; struct node * next; }; //链表创建 no ...

  3. 大数求模 sicily 1020

        Search

  4. UINavigationController的popViewControllerAnimated问题

    UINavigationController是IOS编程中的一个view controller的容器,通过栈管理viewControllers,每一次push操作都将在栈顶添加一个view contr ...

  5. 安装node和grunt

    由于我用的恶事win8的系统,所以在安装nodeJS的时候出现了2503和2502的错误.解决方案: 进入cmd,然后输入msiexec /package [路径:为你将要安装的node所在的位置] ...

  6. mongodb的常用操作(三)

    继续mongodb的学习和总结: 11.mongodb的mapreduce功能 mapreduce可以说是mongodb的一个很强大的功能,可以实现复杂的运算和统计,做一个简要的总结: 假设有user ...

  7. protected internal修饰符

    见过这样的修饰符,但是没有仔细考虑过,今天做一个小练习. 先给出一个链接,别人在网上讨论的:http://wenku.baidu.com/view/4023f65abe23482fb4da4cfe.h ...

  8. Oracle 10g下载链接

    用迅雷下载: http://download.oracle.com/otn/linux/oracle10g/10201/10201_database_linux_x86_64.cpio.gz http ...

  9. c++异常详解

    一.什么是异常处理 一句话:异常处理就是处理程序中的错误. 二.为什么需要异常处理,以及异常处理的基本思想 C++之父Bjarne Stroustrup在<The C++ Programming ...

  10. 【quartz】 入门

    把技术债务给还了,首先来一个最简单的demo: 2.x版比1.x有很多改进,1.x基于fw1.2: 2.x基于fw3.5以上:语法上有很大的不同,摒弃了很多1.x的很多东西: 直接以2.x来demo ...