后缀数组之构建的一目了然说明

什么是后缀数组?

后缀数组是一种解决字符串问题的有力工具。相比于后缀树,它更易于实现且占用内存更少。在实际应用中,后缀数组经常用于解决字符串有关的复杂问题。

先介绍几个后缀数组中的基本定义:

子串:字符串S 的子串r[i..j],i≤j,表示r 串中从i 到j
这一段,也就是顺次排列r[i],r[i+1],...,r[j]形成的字符串。

后缀:后缀是指从某个位置i 开始到整个串末尾结束的一个特殊子串。字符串r 的从第i 个字符开始的后缀表示为Suffix(i) ,
也就是Suffix(i)=r[i..len(r)]。

有点不明白了吧?

来看个简单的后缀数组的构建代码就知道大概是个什么东西了

?





1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

public int[] getSuffixArray(String str) { 

if (str == nullreturn null

// 初始化后缀数组 

String[] suffix = new String[str.length()]; 

for (int i = 0; i < suffix.length; i++) 

suffix[i] = str.substring(i);  

// 对后缀数组排序 

Arrays.sort(suffix);  

// 求结果数组 

int[] result = new int[str.length()];

for (int i = 0; i < suffix.length; i++) { 

result[i] = str.lastIndexOf(suffix[i]); 

}  

return result; 

}

  返回的result数组就是名次数组,意思就是“排第几的是谁?”。

以上面代码为例,假设str="abracadabra"

则suffix[]={

"abracadabra",

"bracadabra",

"racadabra",

"acadabra",

"cadabra",

"adabra",

"dabra",

"abra",

"bra",

"ra",

"a",

""

}

然后对suffix数组排序后,结果:

排完序后,后缀数组表示的意思就是“排第几的是谁?”

接下来result数组就是

result数组表示的意思就是“你排第几?”。

三步中如何对suffix数组排序是最费时的,有一些算法用于处理这事(Ukkonen 算法,DC3
算法,倍增算法等

后缀数组应用

例1:给定一个字符串,求最长重复子串,这两个子串可以重叠。

相邻suffix数组匹配的最长长度

例2:给定两个字符串A 和B,求最长公共子串

先将第二个字符串写在第一个字符串后面,中间用一个没有出现过的字符隔开,再求这个新的字符串的后缀数组,再求最长公共子串

后缀数组之构建的一目了然说明,布布扣,bubuko.com

时间: 2024-08-25 03:40:15

后缀数组之构建的一目了然说明的相关文章

后缀数组(Suffix Array)模板及简析——Part 1:构建SA和rank数组

后缀数组(Suffix Array,SA)是处理字符串的有力工具.它比后缀树更易实现,占用空间更少,并且同样可以解决千变万化的字符串问题 首先推荐罗穗骞的论文(网上搜一下就能搜到),里面对后缀数组的定义.实现和应用都做了详细的阐述 然而不幸的是罗神犇的代码简直魔性,蒟蒻表示这代码压的根本看不懂啊…… 所以在理解了后缀数组的构建过程之后,我重新写了一份模板代码.虽然啰嗦了点(代码比较大,而且变量名故意拉长了),不过相对比较好懂 而且论文中用到的辅助空间是4N,我的模板用了3N,事实上还可以优化到只

poj 3882(Stammering Aliens) 后缀数组 或者 hash

后缀数组:  构建后缀数组,注意要在字符串莫末尾加上一个没出现过的字符.然后可以2分或者直接扫描,直接扫描需要用单调队列来维护 VIEW CODE #include<cstdio> #include<algorithm> #include<iostream> #include<cmath> #include<queue> #include<stack> #include<string> #include<cstrin

后缀数组之倍增算法

首先说明 :后缀数组的构建在网上有多种方法:朴素的n*n*logn,还有倍增n*logn的,还有3*n的DC3算法,当然还有DC算法.这个算法学习自林厚丛老师的<高级数据结构>,代码较长,而且常数也比较大,但是是我这种笨人可以理解的.如有人想学短而快的可以学习<罗穗骞 后缀数组 ---处理字符串的有力工具>.顺便说一下,罗大神的算法书写的的确很短小也漂亮,可惜我看不懂. 说一下学习的心路历程吧!最开始想学后缀树,道理看明的了,可是一看代码实在是太长了(可能是我找的模版不对吧).后来

trie上构建后缀数组

例题: 往事太多,有时候忘了就忘了吧. 如果有非记不可的,就只能用点附加手段啦! 我们定义一棵往事树是一个 n 个点 n-1 条边的有向无环图,点编号为 1到 n,其中 1 号点被称为是根结点,除根结点以外, 每个点都恰有一条出边(即以其作为起点的边). 每条边上有 1 个字符(这里我们实际上用一个不大于 300的非负整数代表不同的字符), 对于任意一个点 u,u 的所有入边(即以其为终点的边)上的字符互不相同. 接下来我们定义往事,点 u 对应的往事为 u 到根的路径(显然有且只有一条)上的所

uva 10829 - L-Gap Substrings(后缀数组)

题目链接:uva 10829 - L-Gap Substrings 题目大意:给定一个字符串,问有多少字符串满足UVU的形式,要求U非空,V的长度为g. 解题思路:对字符串的正序和逆序构建后缀数组,然后枚举U的长度l,每次以长度l分区间,在l和l+d+g所在的两个区间上确定U的最大长度. #include <cstdio> #include <cstring> #include <cstdlib> #include <algorithm> using nam

poj 3693 Maximum repetition substring(后缀数组)

题目链接:poj 3693 Maximum repetition substring 题目大意:求一个字符串中循环子串次数最多的子串. 解题思路:对字符串构建后缀数组,然后枚举循环长度,分区间确定.对于一个长度l,每次求出i和i+l的LCP,那么以i为起点,循环子串长度为l的子串的循环次数为LCP/l+1,然后再考虑一下从i-l+1~i之间有没有存在增长的可能性. #include <cstdio> #include <cstring> #include <vector>

关于后缀数组的一点想法

后缀数组大概就是用后缀排名来搞一些事情,因为字符串中的每一个子串都可看做某一后缀的前缀 可用倍增法求出后缀排名 一.数组意义(对于字符串 s) sa[i]:排名为i的后缀的开头在s中的位置 height[i]:排名为i的后缀和排名为i-1的后缀的LCP(最长公共前缀) c[]:用于基数排序,统计前缀和 rank[i]:以s[i]开头的后缀的排名  显然 rank[sa[i]]=i    sa[rank[i]]=i 二.求sa[]具体思路 1.用倍增法构造第一.第二关键词,第一关键词小的排在前,第

[知识点]后缀数组

// 本文部分内容参照刘汝佳<算法竞赛入门经典训练指南>,特此说明. 1.前言 趁着这几天上午,把后缀数组大致看完了.这个东西本身的概念可能没太大理解问题,但是它所延伸出来的知识很复杂,很多,还有它的两个兄弟——后缀树,后缀自动机,编起来都不是盖的. 2.概念 前面曾经提到过Aho-Corasick自动机(http://www.cnblogs.com/jinkun113/p/4682853.html),讲得有点简略...它用以解决多模板匹配问题.但是前提是事先知道所有的模板,在实际应用中,我们

【POJ1743】Musical Themes 乐曲主题 后缀数组、 (也可以用hash+二分做的~)

题意: 1829: Musical Themes 乐曲主题 Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 42  Solved: 15 [Submit][Status][Web Board] Description 我们用N(1 <= N <=5000)个音符的序列来表示一首乐曲,每个音符都是1..88范围内的整数,每个数表示钢琴上的一个键.很不幸这种表示旋律的方法忽略了音符的时值,但这项编程任务是关于音高的,与时值无关. 许多作曲家围绕一个重