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

    1: 在xp sp2中用mstsc /console命令可以登录到远程桌面的控制台(和在电脑前以同一用户登录),xp升级到sp3后,不能这样用了.sp3中命令应该换成mstsc /admin. 2: ...

  2. shell脚本初识

    #!/bin/bash(linux脚本环境的声明即解释器,该解释器为bash,位于根目录下的bin目录下) 变量的定义与赋值: 格式:变量名=变量值(无需声明变量类型) 变量的引用: 格式:$变量名 ...

  3. IP进制站群原理

    百度搜索:“inurl:0×00”,会发现全是以八进制.十六进制形式显示的域名(如下图),当点击后,浏览器会自动将这些域名转换为十进制的ip.这种方式在黑帽圈目前挺火爆的,用于做长尾词排名,可以带来可 ...

  4. JVM学习---JAVA内存

    一.JAVA运行时数据区域:JAVA中的运行时内存区域有的随着虚拟机进程的启动而存在,有的区域则是依赖用户线程的启动和结束而建立和销毁的.包括以下的几个区域. 图. JAVA虚拟机运行时数据区 1.程 ...

  5. Demo学习: Basic jQuery

    UniGUI是一套基于ExtJS的Delphi的WEB框架,它是使用ExtPascal来转化到ExtJS,ExtJS是一个跨浏览器的JavaScript库,因此UniGUI发布出来的程序可以在各种浏览 ...

  6. 使用CSS画一个三角形

    <div style="width:0px;height:0px;border-width:40px;border-style:solid;border-color:transpare ...

  7. XAML 概述四

    这一节我们来简单介绍一下XAML的加载和编译,它包括如下三种方式:  · 只使用代码  · 使用代码和未编译的XAML  · 使用代码和编译过的BAML 一. 只使用代码 我们首先创建一个简单的控制台 ...

  8. Windows Form 分页。

    其实功能实现很简单.我做的是一个通用的分页控件.项目时间很紧,可能有点粗糙.欢迎大家斧正.不说了直接贴代码吧. using System; using System.Collections.Gener ...

  9. 什么是 block

    什么是 block 1.提前准备好的一段可以执行的代码 2.block 可以当做参数传递 3.在需要的时候执行 block 4,block 中使用 self 时肯产生循环引用 block 做网络异步耗 ...

  10. 回溯(su)算法之N皇后问题

    这里回溯算法还要好好研究一下 试探一个位置是否有效,如果有效,试探下一个位置(DFS),如果无效则回退 1.定义一个解空间,存放一个解的空间 2.DFS(暂且认为是DFS) 这里N皇后用的是递归+回溯 ...