poj2774

题意

求两个字符串的最长公共子串

分析

论文

将两个字符串合并,中间插入分隔符,在找最大的 height 值的时候保证,两个字符串后缀的起始点分别来自原来的两个字符串。

code

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. using namespace std;
  5. const int MAXN = 2e5 + 10;
  6. char s[MAXN], s2[MAXN];
  7. int sa[MAXN], t[MAXN], t2[MAXN], c[MAXN], n; // n 为 字符串长度 + 1,s[n - 1] = 0
  8. int rnk[MAXN], height[MAXN];
  9. // 构造字符串 s 的后缀数组。每个字符值必须为 0 ~ m-1
  10. void build_sa(int m) {
  11. int i, *x = t, *y = t2;
  12. for(i = 0; i < m; i++) c[i] = 0;
  13. for(i = 0; i < n; i++) c[x[i] = s[i]]++;
  14. for(i = 1; i < m; i++) c[i] += c[i - 1];
  15. for(i = n - 1; i >= 0; i--) sa[--c[x[i]]] = i;
  16. for(int k = 1; k <= n; k <<= 1) {
  17. int p = 0;
  18. for(i = n - k; i < n; i++) y[p++] = i;
  19. for(i = 0; i < n; i++) if(sa[i] >= k) y[p++] = sa[i] - k;
  20. for(i = 0; i < m; i++) c[i] = 0;
  21. for(i = 0; i < n; i++) c[x[y[i]]]++;
  22. for(i = 0; i < m; i++) c[i] += c[i - 1];
  23. for(i = n - 1; i >= 0; i--) sa[--c[x[y[i]]]] = y[i];
  24. swap(x, y);
  25. p = 1; x[sa[0]] = 0;
  26. for(i = 1; i < n; i++)
  27. x[sa[i]] = y[sa[i - 1]] == y[sa[i]] && y[sa[i - 1] + k] == y[sa[i] + k] ? p - 1 : p++;
  28. if(p >= n) break;
  29. m = p;
  30. }
  31. }
  32. void getHeight() {
  33. int i, j, k = 0;
  34. for(i = 0; i < n; i++) rnk[sa[i]] = i;
  35. for(i = 0; i < n - 1; i++) {
  36. if(k) k--;
  37. j = sa[rnk[i] - 1];
  38. while(s[i + k] == s[j + k]) k++;
  39. height[rnk[i]] = k;
  40. }
  41. }
  42. void debug() {
  43. scanf("%s", s);
  44. n = strlen(s) + 1;
  45. build_sa(128);
  46. getHeight();
  47. for(int i = 1; i < n; i++) printf("%d ", sa[i]); puts("");
  48. for(int i = 2; i < n; i++) printf("%d ", height[i]);
  49. // a b a a b
  50. // 2 3 0 4 1 : aab ab abaab b baab
  51. // 1 2 0 1
  52. }
  53. // 后缀数组是“排第几的是谁?”,名次数组是“你排第几?”
  54. // 保证 s[n-1] = 0 且前面非 0 // 也就是说空串在最前
  55. // sa[0] = n - 1,sa[i] 有效的只有 [1, n-1] ( 因为前面的 n 加 1 了 )表示第 i 位的是谁( 以第几个字符开始的字符串后缀 )
  56. // height[i] 有效的只有 [2, n-1] 表示 lcp(sa[i], sa[i-1]) 最长公共前缀
  57. int main() {
  58. scanf("%s%s", s, s2);
  59. int l1 = strlen(s), l2 = strlen(s2);
  60. s[l1++] = '#';
  61. for(int i = l1; i < l1 + l2; i++) s[i] = s2[i - l1];
  62. n = strlen(s) + 1; // 最后一位留空
  63. build_sa(128);
  64. getHeight();
  65. int ans = 0;
  66. for(int i = 2; i < n; i++) {
  67. if(height[i] > ans && ((sa[i] < l1) != (sa[i - 1] < l1)))
  68. ans = height[i];
  69. }
  70. printf("%d\n", ans);
  71. return 0;
  72. }

poj2774(最长公共子串)的更多相关文章

  1. POJ2774 Long Long Message —— 后缀数组 两字符串的最长公共子串

    题目链接:https://vjudge.net/problem/POJ-2774 Long Long Message Time Limit: 4000MS   Memory Limit: 131072 ...

  2. poj2774 Long Long Message 后缀数组求最长公共子串

    题目链接:http://poj.org/problem?id=2774 这是一道很好的后缀数组的入门题目 题意:给你两个字符串,然后求这两个的字符串的最长连续的公共子串 一般用后缀数组解决的两个字符串 ...

  3. [URAL-1517][求两个字符串的最长公共子串]

    Freedom of Choice URAL - 1517 Background Before Albanian people could bear with the freedom of speec ...

  4. [Data Structure] LCSs——最长公共子序列和最长公共子串

    1. 什么是 LCSs? 什么是 LCSs? 好多博友看到这几个字母可能比较困惑,因为这是我自己对两个常见问题的统称,它们分别为最长公共子序列问题(Longest-Common-Subsequence ...

  5. HDU 1503 带回朔路径的最长公共子串

    http://acm.hdu.edu.cn/showproblem.php?pid=1503 这道题又WA了好几次 在裸最长公共子串基础上加了回溯功能,就是给三种状态各做一个 不同的标记.dp[n][ ...

  6. 最长公共子序列PK最长公共子串

    1.先科普下最长公共子序列 & 最长公共子串的区别: 找两个字符串的最长公共子串,这个子串要求在原字符串中是连续的.而最长公共子序列则并不要求连续. (1)递归方法求最长公共子序列的长度 1) ...

  7. 动态规划(一)——最长公共子序列和最长公共子串

    注: 最长公共子序列采用动态规划解决,由于子问题重叠,故采用数组缓存结果,保存最佳取值方向.输出结果时,则自顶向下建立二叉树,自底向上输出,则这过程中没有分叉路,结果唯一. 最长公共子串采用参考串方式 ...

  8. 字符串hash + 二分答案 - 求最长公共子串 --- poj 2774

    Long Long Message Problem's Link:http://poj.org/problem?id=2774 Mean: 求两个字符串的最长公共子串的长度. analyse: 前面在 ...

  9. 后缀数组(模板题) - 求最长公共子串 - poj 2774 Long Long Message

    Language: Default Long Long Message Time Limit: 4000MS   Memory Limit: 131072K Total Submissions: 21 ...

随机推荐

  1. python学习笔记四:lambda表达式和switch

    一.定义 lambda arg1,arg2... : returnValue 二.示例 #!/usr/bin/python def f(x,y): return x*y print f(2,3) g ...

  2. jmeter运行脚本后,请求偶发性的传参错误

    问题现象:jmeter写好脚本后,请求偶发性的传参错误 排查过程:1.结合报错返回值,看是不是线程并发引起: 2.排除线程并发引起后,看看是不是取值策略:如果是参数化,看看是不是每次迭代,每次都取唯一 ...

  3. 你的第一个自动化测试:Selenium 自动化测试

    前言: 让你掌握自动化测试暂时脱离手工点点点,本章节让你掌握 Selenium 如何定位.判定.操作元素(实现业务逻辑) 一. 前期准备 1.准备以下工具 1.Selenium下载地址:立即下载 2. ...

  4. pytest单元测试框架

    一.安装方式 1.安装命令:pip install pytest 2.html安装插件:pip install pytest -html 二.pytest执行指定测试用例 1.思想:通过对测试用例进行 ...

  5. java_链表反转

    定义一个Node节点类 1 public class Node { 2 public int value; 3 public Node next; 4 5 public Node(int value) ...

  6. JavaSE复习(一)继承多态与常用API

    继承与多态 在父子类的继承关系当中,如果成员变量重名,则创建子类对象时,访问有两种方式: 直接通过子类对象访问成员变量:等号左边是谁,就优先用谁,没有则向上找 间接通过成员方法访问成员变量:该方法属于 ...

  7. .export*读取图片

    *读取图片 read_image(Image,'D:/MyFile/halcon/数字识别/1.jpg define PHYS_FLASH2_1 0xBC000000 /* Image2 Bank # ...

  8. web服务器集群session同步

    在做了web集群后,你肯定会首先考虑session同步问题,因为通过负载均衡后,同一个IP访问同一个页面会被分配到不同的服务器上,如果session不同步的话,一个登录用户,一会是登录状态,一会又不是 ...

  9. Hash表模板

    namespace Hash { ; ; struct adj { ll nxt,v,num,val; }e[N]; ll head[H],ecnt=; void init() { ecnt=; me ...

  10. Linux系统—— core 文件

    Linux core 文件介绍 1. core文件的简单介绍 在一个程序崩溃时,它一般会在指定目录下生成一个core文件.core文件仅仅是一个内存映象(同时加上调试信息),主要是用来调试的. 2. ...