题目链接:POJ - 2774

题目分析

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

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

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

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

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

代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm> 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;
}

  

[POJ 2774] Long Long Message 【后缀数组】的更多相关文章

  1. POJ 2774 Long Long Message 后缀数组

    Long Long Message   Description The little cat is majoring in physics in the capital of Byterland. A ...

  2. poj 2774 Long Long Message 后缀数组基础题

    Time Limit: 4000MS   Memory Limit: 131072K Total Submissions: 24756   Accepted: 10130 Case Time Limi ...

  3. poj 2774 Long Long Message 后缀数组LCP理解

    题目链接 题意:给两个长度不超过1e5的字符串,问两个字符串的连续公共子串最大长度为多少? 思路:两个字符串连接之后直接后缀数组+LCP,在height中找出max同时满足一左一右即可: #inclu ...

  4. POJ 2774 Long Long Message 后缀数组模板题

    题意 给定字符串A.B,求其最长公共子串 后缀数组模板题,求出height数组,判断sa[i]与sa[i-1]是否分属字符串A.B,统计答案即可. #include <cstdio> #i ...

  5. POJ 2774 Long Long Message (后缀数组+二分)

    题目大意:求两个字符串的最长公共子串长度 把两个串接在一起,中间放一个#,然后求出height 接下来还是老套路,二分出一个答案ans,然后去验证,如果有连续几个位置的h[i]>=ans,且存在 ...

  6. POJ - 2774 Long Long Message (后缀数组/后缀自动机模板题)

    后缀数组: #include<cstdio> #include<algorithm> #include<cstring> #include<vector> ...

  7. POJ 2774 Long Long Message ——后缀数组

    [题目分析] 用height数组RMQ的性质去求最长的公共子串. 要求sa[i]和sa[i-1]必须在两个串中,然后取height的MAX. 利用中间的字符来连接两个字符串的思想很巧妙,记得最后还需要 ...

  8. PKU 2774 Long Long Message (后缀数组练习模板题)

    题意:给你两个字符串.求最长公共字串的长度. by:罗穗骞模板 #include <iostream> #include <stdio.h> #include <stri ...

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

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

随机推荐

  1. 构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(28)-系统小结

    原文:构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(28)-系统小结 我们从第一节搭建框架开始直到二十七节,权限管理已经告一段落,相信很多有跟上来的园友,已经 ...

  2. spring MVC 整合mongodb

    Spring Mongodb 目录 1 SPRING整合MONGODB 1 1.1 环境准备 1 1.2 包依赖 1 1.3 配置 2 2 案列 5 2.1 SPRING MVC整合MONGODB代码 ...

  3. JWS-webservice 与Axis2-webservice的高速实现

    在详细介绍这两种框架下的webservice之前,先跟大家交流一下SOA认识,也就是面向服务的体系结构.SOA所要解决的主要问题是在现有基础环境的前提下,通过对现有应用程序和基础结构进行又一次的组合以 ...

  4. MapReduce明星搜索指数统计,找出人气王

    我们继续通过项目强化掌握Combiner和Partitioner优化Hadoop性能 1.项目介绍 本项目我们使用明星搜索指数数据,分别统计出搜索指数最高的男明星和女明星. 2.数据集 3.分析 基于 ...

  5. Java设计模式02:常用设计模式之工厂模式(创建型模式)

    一.工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的.  工厂模式在<Java与模式>中分为三类: 1)简单工厂模式(Simple Fact ...

  6. codevs 1817 灾后重建

    /* 暴力暴力 离线每次添边 堆优化dij 70 SPFA 80..... */ #include<iostream> #include<cstdio> #include< ...

  7. 9.23 noip模拟试题

      Problem 1 抓牛(catchcow.cpp/c/pas) [题目描述] 农夫约翰被通知,他的一只奶牛逃逸了!所以他决定,马上出发,尽快把那只奶牛抓回来. 他们都站在数轴上.约翰在N(O≤N ...

  8. js 的post提交的写法

    function AddEditDevice(data){ var form = $("#deviceEditform"); if (form.length == 0) { for ...

  9. aliyun云服务器硬件性能测试

    1.所购买阿里云服务器信息 2.dd命令测试 3.

  10. 后台线程,优先级,sleep,yield

    1.后台线程,是指在程序运行的时候在后台提供一种通用服务的线程,并且这种线程并不属于程序中不可获取的部分.当所有非后台线程结束时,程序也就 终止了,同时会杀死进程中所有后台线程.main()是一个非后 ...