poj2774

题意

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

分析

论文

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

code

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN = 2e5 + 10;
char s[MAXN], s2[MAXN];
int sa[MAXN], t[MAXN], t2[MAXN], c[MAXN], n; // n 为 字符串长度 + 1,s[n - 1] = 0 int rnk[MAXN], height[MAXN];
// 构造字符串 s 的后缀数组。每个字符值必须为 0 ~ m-1
void build_sa(int m) {
int i, *x = t, *y = t2;
for(i = 0; i < m; i++) c[i] = 0;
for(i = 0; i < n; i++) c[x[i] = s[i]]++;
for(i = 1; i < m; i++) c[i] += c[i - 1];
for(i = n - 1; i >= 0; i--) sa[--c[x[i]]] = i;
for(int k = 1; k <= n; k <<= 1) {
int p = 0;
for(i = n - k; i < n; i++) y[p++] = i;
for(i = 0; i < n; i++) if(sa[i] >= k) y[p++] = sa[i] - k;
for(i = 0; i < m; i++) c[i] = 0;
for(i = 0; i < n; i++) c[x[y[i]]]++;
for(i = 0; i < m; i++) c[i] += c[i - 1];
for(i = n - 1; i >= 0; i--) sa[--c[x[y[i]]]] = y[i];
swap(x, y);
p = 1; x[sa[0]] = 0;
for(i = 1; i < n; i++)
x[sa[i]] = y[sa[i - 1]] == y[sa[i]] && y[sa[i - 1] + k] == y[sa[i] + k] ? p - 1 : p++;
if(p >= n) break;
m = p;
}
}
void getHeight() {
int i, j, k = 0;
for(i = 0; i < n; i++) rnk[sa[i]] = i;
for(i = 0; i < n - 1; i++) {
if(k) k--;
j = sa[rnk[i] - 1];
while(s[i + k] == s[j + k]) k++;
height[rnk[i]] = k;
}
}
void debug() {
scanf("%s", s);
n = strlen(s) + 1;
build_sa(128);
getHeight();
for(int i = 1; i < n; i++) printf("%d ", sa[i]); puts("");
for(int i = 2; i < n; i++) printf("%d ", height[i]);
// a b a a b
// 2 3 0 4 1 : aab ab abaab b baab
// 1 2 0 1
} // 后缀数组是“排第几的是谁?”,名次数组是“你排第几?” // 保证 s[n-1] = 0 且前面非 0 // 也就是说空串在最前 // sa[0] = n - 1,sa[i] 有效的只有 [1, n-1] ( 因为前面的 n 加 1 了 )表示第 i 位的是谁( 以第几个字符开始的字符串后缀 )
// height[i] 有效的只有 [2, n-1] 表示 lcp(sa[i], sa[i-1]) 最长公共前缀 int main() {
scanf("%s%s", s, s2);
int l1 = strlen(s), l2 = strlen(s2);
s[l1++] = '#';
for(int i = l1; i < l1 + l2; i++) s[i] = s2[i - l1];
n = strlen(s) + 1; // 最后一位留空
build_sa(128);
getHeight();
int ans = 0;
for(int i = 2; i < n; i++) {
if(height[i] > ans && ((sa[i] < l1) != (sa[i - 1] < l1)))
ans = height[i];
}
printf("%d\n", ans);
return 0;
}

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. [转载]unity优化1

    官方优化文档--优化图像性能http://docs.unity3d.com/Documentation/Manual/OptimizingGraphicsPerformance.html Unity3 ...

  2. NBA投篮

    D 辅助插件:原生 游戏制作难度系数:初级 游戏教程网址:http://www.raywenderlich.com/20333/beginning-unity-3d-for-ios-part-1 1. ...

  3. 孤荷凌寒自学python那些事第一天

    孤荷凌寒自学python第一天 初识python (学习过程的完整录像分享链接在文末,手写笔记图片在文末) 一种编程语言,首先是它的语言的基本架构,python总体让人耳目一新: 今天其实只接触到了它 ...

  4. 【LeetCode】Swap Nodes in Pairs(两两交换链表中的节点)

    这是LeetCode里的第24题. 题目要求: 给定一个链表,两两交换其中相邻的节点,并返回交换后的链表. 示例: 给定1->2->3->4, 你应该返回2->1->4- ...

  5. Visual C++ 图像处理类库CxImage源代码

    说明:VC++ 图像处理类库CxImage源代码,CxImage是一个可以用于MFC 的C++类,可以打开,保存,显示,转换各种格式的图像文件,比如BMP, JPEG, GIF, PNG, TIFF, ...

  6. 团队项目-第一次Scrum 会议

    时间:10.23 时长:30分钟 地点:F楼2层沙发休息处 工作情况 团队成员 已完成任务 待完成任务 解小锐 学习使用cocos creator 学习官方样例 陈鑫 学习JavaScript 学习c ...

  7. 01、dos命令行的常用命令

    cd 进入指定目录cd..  返回上一级目录cd\   退回盘符根目录dir        列出当前目录下的文件以及文件夹md       创建目录rd 删除目录del   删除文件cls       ...

  8. 小木乃伊到我家 dijkstra + 链表 + 优先队列

    https://ac.nowcoder.com/acm/contest/96/E?&headNav=www&headNav=acm 题目描述   AA的欧尼酱qwb是个考古学家,有一天 ...

  9. intellij idea 2017 工具使用问题

    1.打开idea 打开maven项目报错:Unable to import maven project 2.在idea中Help->Show Log in Explorer->idea.l ...

  10. 【bzoj4818】[Sdoi2017]序列计数 矩阵乘法

    原文地址:http://www.cnblogs.com/GXZlegend/p/6825132.html 题目描述 Alice想要得到一个长度为n的序列,序列中的数都是不超过m的正整数,而且这n个数的 ...