博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[POJ 2774] Long Long Message 【后缀数组】
阅读量:5266 次
发布时间:2019-06-14

本文共 2308 字,大约阅读时间需要 7 分钟。

题目链接:

 

题目分析

题目要求求出两个字符串的最长公共子串,使用后缀数组求解会十分容易。

将两个字符串用特殊字符隔开再连接到一起,求出后缀数组。

可以看出,最长公共子串就是两个字符串分别的一个后缀的 LCP ,并且这两个后缀在 SA 中一定是相邻的。

那么他们的 LCP 就是 Height[i] ,当然,Height[i] 的最大值不一定就是 LCS ,因为可能 SA[i] 和 SA[i-1] 是在同一个字符串中。

那么判断一下,如果 SA[i] 与 SA[i - 1] 分别在两个字符串中,就用 Height[i] 更新 Ans 。

 

代码

#include 
#include
#include
#include
#include
#include
using namespace std;const int MaxL = 200000 + 15;int n, l1, l2, Ans;int A[MaxL], Rank[MaxL], Height[MaxL], SA[MaxL];int VA[MaxL], VB[MaxL], VC[MaxL], Sum[MaxL];char S1[MaxL], S2[MaxL];inline bool Cmp(int *a, int x, int y, int l) { return (a[x] == a[y]) && (a[x + l] == a[y + l]);}void DA(int *A, int n, int m) { int *x, *y, *t; x = VA; y = VB; for (int i = 1; i <= m; ++i) Sum[i] = 0; for (int i = 1; i <= n; ++i) ++Sum[x[i] = A[i]]; for (int i = 2; i <= m; ++i) Sum[i] += Sum[i - 1]; for (int i = n; i >= 1; --i) SA[Sum[x[i]]--] = i; int p, q; p = 0; for (int j = 1; p < n; j <<= 1, m = p) { q = 0; for (int i = n - j + 1; i <= n; ++i) y[++q] = i; for (int i = 1; i <= n; ++i) { if (SA[i] <= j) continue; y[++q] = SA[i] - j; } for (int i = 1; i <= n; ++i) VC[i] = x[y[i]]; for (int i = 1; i <= m; ++i) Sum[i] = 0; for (int i = 1; i <= n; ++i) ++Sum[VC[i]]; for (int i = 2; i <= m; ++i) Sum[i] += Sum[i - 1]; for (int i = n; i >= 1; --i) SA[Sum[VC[i]]--] = y[i]; t = x; x = y; y = t; x[SA[1]] = 1; p = 1; for (int i = 2; i <= n; ++i) x[SA[i]] = Cmp(y, SA[i], SA[i - 1], j) ? p : ++p; } for (int i = 1; i <= n; ++i) Rank[SA[i]] = i; //GetHeight int h, o; h = 0; for (int i = 1; i <= n; ++i) { if (Rank[i] == 1) continue; o = SA[Rank[i] - 1]; while (A[i + h] == A[o + h]) ++h; Height[Rank[i]] = h; if (h > 0) --h; } }int main() { scanf("%s%s", S1 + 1, S2 + 1); l1 = strlen(S1 + 1); l2 = strlen(S2 + 1); for (int i = 1; i <= l1; ++i) A[i] = S1[i] - 'a' + 1; A[l1 + 1] = 27; for (int i = 1; i <= l2; ++i) A[l1 + 1 + i] = S2[i] - 'a' + 1; A[l1 + 1 + l2 + 1] = 28; n = l1 + 1 + l2 + 1; DA(A, n, 28); Ans = 0; for (int i = 2; i <= n - 1; ++i) { if (Height[i] > Ans) { if (SA[i] <= l1 && SA[i - 1] > l1 + 1) Ans = Height[i]; if (SA[i] > l1 + 1 && SA[i - 1] <= l1) Ans = Height[i]; } } printf("%d\n", Ans); return 0;}

  

转载于:https://www.cnblogs.com/JoeFan/p/4215158.html

你可能感兴趣的文章
dom4j 通用解析器,解析成List<Map<String,Object>>
查看>>
第一个项目--用bootstrap实现美工设计的首页
查看>>
使用XML传递数据
查看>>
TYVJ.1864.[Poetize I]守卫者的挑战(概率DP)
查看>>
基于CMMI的敏捷开发过程文档裁剪
查看>>
0925 韩顺平java视频
查看>>
软件需求规格说明书
查看>>
53. Maximum Subarray
查看>>
iOS-程序启动原理和UIApplication
查看>>
SpringMVC入门(二)—— 参数的传递、Controller方法返回值、json数据交互、异常处理、图片上传、拦截器...
查看>>
git的安装
查看>>
mysql 8.0 zip包安装
查看>>
Spring框架系列(三)--Bean的作用域和生命周期
查看>>
springboot + mybatis
查看>>
awk 统计
查看>>
CSS min-height 属性
查看>>
SDN第一次作业
查看>>
模板设计模式的应用
查看>>
【井字游戏】做一款回忆童年的游戏
查看>>
数据结构(二):栈
查看>>