学后缀数组后的一道裸题。先来讲讲收获,作为字符串初学者,后缀数组也是刚刚在学,所幸的是有一篇好的论文《后缀数组--处理字符串的有力工具》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. js 函数的调用模式

    1.函数调用 调用一个函数将暂停当前函数的执行,传递控制权和参数给新函数.除了函数声明时定义的形参,每个函数还接受两个附加的参数:this和arguments(arguments并不是一个真正的数组, ...

  2. MySQL 5.7 Zip 安装(win7)

    参考官方文档 http://dev.mysql.com/doc/refman/5.7/en/windows-install-archive.html 2.3.5.1 Extracting the In ...

  3. Ant打jar包指定MainClass

    一般用ant打jar的时候不用指定程序的入口!这个jar一般是给其他app引用的. 但是如果该jar就是程序的启动jar.例如: java -jar abc.jar  这个时候需要指定jar的入口类! ...

  4. iOS Foundation框架 -2.常用集合类简单总结

    Foundation框架中常用的类有:NSString.NSArray.NSSet.NSDictionary 以及它们对应的子类 NSMutableString.NSMutableArray.NSMu ...

  5. ●linux进程的查看与操作●

    查看进程:ps -le | more ,ps -aux | more ,ps & 后台运行  jobs 查看后台进程  fg [n]调到前台  bg放到后台 ctrl +c 终止  ctrl ...

  6. Nginx +keepalived

    Nginx +keepalived   配置高可用的Nginx 准备环境: 节点node17,node18   lftp 172.16.0.1:/pub/Sources/6.x86_64/nginx ...

  7. wap网站seo如何优化呢?

    从事互联网的人员都知道移动互联网营销是一个大的趋势,但是要怎么去做恐怕还都一筹莫展.由PC端的网络营销的经验和常识来看,首要的是要做好移动端手机网站的优化工作.据观察分析,目前国内的大多数并没有做好手 ...

  8. 安卓4.0下rem显示不正常的问题

    在项目中使用了rem为单位,结果在Oppo和4.0下某些浏览器rem工作不正常,font-size计算出来的px总是大于预期的值,因此加了个Hack var docEl = doc.documentE ...

  9. mongodb的常用操作

    对于nosql之前工作中有用到bekerlydb,最近开始了解mongodb,先简单写下mongodb的一些常用操作,当是个总结: 1.mongodb使用数据库(database)和集合(collec ...

  10. C# 发邮件类可发送附件

    using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Ne ...