学后缀数组后的一道裸题。先来讲讲收获,作为字符串初学者,后缀数组也是刚刚在学,所幸的是有一篇好的论文《后缀数组--处理字符串的有力工具》by 罗穗骞,里面非常详尽地介绍了有关后缀数组的概念,也就是sa[i]和rk[i]表示的是什么。理解了它们互为逆运算后就不难理解sa[rk[i]]=i rk[sa[i]]=i,所以知道其中一个就可以知道另外一个,然后学习了一下后缀数组中的倍增算法构建,虽然效率比不上线性的算法,但是胜在好理解,好写。当然大神的代码我是不怎么懂,我就翻阅了另一本书《挑战程序设计竞赛》里的代码,总之就是两个材料一起看,搞懂了什么是高度数组lcp, 也知道了h[i]>=h[i-1]-1,理解这个不等式我觉得挺关键的,利用这一点就可以写出一个线性的算法求出高度数组。高度数组的一个应用就是求两个串的最长公共子串。对于S1和S2,我们构造一个新串S1#S2,然后建立后缀数组,求出lcp,可以证明的是,最长公共前缀一定是出现在后缀数组中相邻的两个子串里的(否则越离越远,只可能更小)。利用这一点,我们找出满足sa[i]和sa[i+1]分属于S1,S2的串,然后对应的lcp[i]的最大值就是答案。代码完全参(zhao)考(chao)挑战程序设计竞赛,写下来权当学习。。

#pragma warning(disable:4996)
#include<iostream>
#include<cstring>
#include<algorithm>
#include<string>
#include<vector>
#include<cmath>
#include<cstdio>
#define maxn 500000
using namespace std; int rk[maxn+50], sa[maxn+50],lcp[maxn+50];
int tmp[maxn + 50];
int k,n;
bool cmp_sa(int i, int j)
{
if (rk[i] != rk[j]) return rk[i] < rk[j];
else {
int ri = i + k <= n ? rk[i + k] : -1;
int rj = j + k <= n ? rk[j + k] : -1;
return ri < rj;
}
} void construct_sa(char *s, int *sa)
{
n = strlen(s);
for (int i = 0; i <= n; i++){
sa[i] = i;
rk[i] = i < n ? s[i] : -1;
}
for (k = 1; k <= n; k <<= 1)
{
sort(sa, sa + n + 1, cmp_sa);
tmp[sa[0]] = 0;
for (int i = 1; i <= n; i++)
{
tmp[sa[i]] = tmp[sa[i - 1]] + (cmp_sa(sa[i - 1], sa[i]) ? 1 : 0);
}
for (int i = 0; i <= n; i++){
rk[i] = tmp[i];
}
}
} void construct_lcp(char *s, int *sa, int *lcp)
{
n = strlen(s);
for (int i = 0; i <= n; i++) rk[sa[i]] = i;
int h = 0;
lcp[0] = 0;
for (int i = 0; i < n; i++){
int j = sa[rk[i] - 1];
for (h ? h-- : 0; j + h < n&&i + h < n&&s[j + h] == s[i + h]; h++);
lcp[rk[i] - 1] = h;
}
} char str1[maxn + 50], str2[maxn + 50]; int main()
{
int T; cin >> T; getchar();
while (T--)
{
gets(str1);
gets(str2);
int len = strlen(str1);
str1[len] = '#';
str1[len + 1] = '\0';
strcat(str1, str2);
construct_sa(str1 ,sa);
construct_lcp(str1,sa,lcp);
int ans = 0;
for (int i = 0; i < strlen(str1); i++)
{
if ((sa[i] < len) != (sa[i + 1]) < len){
ans = max(ans, lcp[i]);
}
}
printf("Nejdelsi spolecny retezec ma delku %d.\n", ans);
}
return 0;
}

  

POJ2217 Secretary 后缀数组&&高度数组的更多相关文章

  1. POJ 3080 Blue Jeans 后缀数组, 高度数组 难度:1

    题目 http://poj.org/problem?id=3080 题意 有m个(2<=m<=10)不包含空格的字符串,长度为60个字符,求所有字符串中都出现过的最长公共子序列,若该子序列 ...

  2. poj2217 Secretary 后缀数组

    #include <iostream> #include <cstring> #include <string> #include <cstdio> u ...

  3. HDU-1403-Longest Common Substring(后缀数组的高度数组运用)

    这题要求两个串中的最长相同子串的长度.高度数组可以求一个串中的最长相同子串的长度.所以想到把两个串连起来,但是这样又会产生一些新的串(第一个串的结尾和第二个串的开头组成的)于是在两个串中间放一个'\0 ...

  4. Z :彻底了解指针数组,数组指针以及函数指针 [复

    原创 :彻底了解指针数组,数组指针以及函数指针 [复制链接] 00 roking 白手起家 帖子 60 主题 16 精华 0 可用积分 74 专家积分 0 在线时间 0 小时 注册时间 2003-10 ...

  5. 指针数组 vs 数组指针

        指针数组,故名思义,就是指针的数组,数组的元素是指针:     数组指针,同样,就是直想数组的指针.     简单举例说明:     int *p[2]; 首先声明了一个数组,数组的元素是in ...

  6. Java 一维数组 二维数组 三维数组

    二维数组包含一位数组  三维数组就是在二维数组的基础上,再加一层.把二维数组看做是一维数组就可以了,按照上述理解类推.   下面是 一维 二维 三维数组例子   一维数组: int[] array1 ...

  7. C++中,指针数组和数组指针

    这俩兄弟长得实在太像,以至于经常让人混淆.然而细心领会和甄别就会发现它们大有不同. 前者是指针数组,后者是指向数组的指针.更详细地说. 前: 指针数组;是一个元素全为指针的数组. 后: 数组指针;可以 ...

  8. 在主方法中定义一个大小为10*10的二维字符型数组,数组名为y,正反对角线上存的是‘*’,其余 位置存的是‘#’;输出这个数组中的所有元素。

    //在主方法中定义一个大小为10*10的二维字符型数组,数组名为y,正反对角线上存的是‘*’,其余 位置存的是‘#’:输出这个数组中的所有元素. char [][]y=new char [10][10 ...

  9. 在主方法中定义一个大小为50的一维整型数组,数组i名为x,数组中存放着{1,3,5,…,99}输出这个数组中的所有元素,每输出十个换一行

    package hanqi; import java.util.Scanner; public class Test7 { public static void main(String[] args) ...

随机推荐

  1. pancake的排序- 1.3 一摞烙饼的排序 《编程之美》读书笔记03

    问题:     星期五的晚上,一帮同事在希格玛大厦附近的“硬盘酒吧”多喝了几杯.程序员多喝了几杯之后谈什么呢?自然是算法问题.有个同事说:“我以前在餐馆打工,顾客经常点非常多的烙饼.店里的饼大小不一, ...

  2. Centos文本方式安装情况下lvm分区的创建

    作者:马 岩(Furzoom) (http://www.cnblogs.com/furzoom/)版权声明:本文的版权归作者与博客园共同所有.转载时请在明显地方注明本文的详细链接,未经作者同意请不要删 ...

  3. 20130909QA整理笔记

    做项目里遇到的一些问题!! 1.滚动条样式 webkit可以使用css来调节滚动条样式: http://www.cnblogs.com/rubylouvre/archive/2011/03/01/19 ...

  4. HTML5 manifest ApplicationCache

    使用 HTML5,通过创建 cache manifest 文件,可以轻松地创建 web 应用的离线版本. HTML5引入了应用程序缓存,这意味着 web 应用可进行缓存,并可在没有因特网连接时进行访问 ...

  5. 【Qt】Qt环境搭建(Qt Creator)【转】

    简述 上一节中介绍了如何进行Qt和Visual Studio的下载安装,随后演示了如何将Qt集成到Visual Studio中,并完成了我们第一个Qt小程序-Hello World.下面主要讲解如何利 ...

  6. 使用MongoDB的开源项目

    根据谷歌的搜索结果筛选出来的. 统计应用 counlty https://count.ly/ mongopress 开源CMS系统 http://www.mongopress.org/ Rubedo ...

  7. AJAX请求和跨域请求详解(原生JS、Jquery)

    一.概述 AJAX 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术. AJAX = 异步 JavaScript 和 XML,是一种用于创建快速动态网页的技术.通过在后台与服务器进行少量数 ...

  8. Png图片的透明部分穿透测试

           private void Window_MouseMove(object sender, MouseEventArgs e){ NavBtnList.Clear(); Point mou ...

  9. 无法创建链接服务器 "TEST" 的 OLE DB 访问接口 "OraOLEDB.Oracle" 的实例

    在使用SQLserver建立远程服务连接Oracle的时候出现先下面错误 出现这个错误,我找到最常见的两个原因 1.注册表 <1>按下WIN+R,打开“运行”窗口,输入“regedit”, ...

  10. OPatch failed with error code 73

    前几天给一套LINUX下的RAC数据库打补丁升级,有一台机器更新失败了,相关的异常内容如下: Restoring "/u01/app/oracle/11.2.0/db_1" to ...