on
on

Leetcode困难题——1044.最长重复子串

Author:

前情,字符串的字典序后缀排序

后缀倍增排序

定义:

字符串:连续的一段字符组成的串叫做字符串,更广义的,任何一个可比较大小的元素组成的数组都可称为字符串。

后缀:suffix(i) 表示字符串 s 从第 i 个位置开始的后缀,即由s[i]~s[n-1]组成的子串

比较:两个字符串大小的比较,从首位开始,一位一位按照 ASCII 进行比较,认为ASCII较小的字符串更小,如果一个字符串比较完了最后一位而另一个没有,则认为前者较小,如果两个字符串长度相同并且所有位置上的字符均相同,则认为两个字符串相等。

后缀数组:sa[] 是一个一维数组,保存了对字符串 s 的所有后缀排序后的结果。表示第 i 小的后缀在原串中的起始位置。

名次数组:rank[] 是一个一维数组,按起始位置保存了每个后缀在 sa[] 中的排名,rank[i]表示 suffix(i)的排名,是一个反向映射表,即 rank[sa[i]] = i 。

高度数组:height[] 是一个一维数组,保存了相邻两个后缀的最长公共前缀(Longest Common Prefix, LCP)长度。

倍增算法:暂时忽略

SA-IS算法:

SA-IS算法可以在线性时间内构造后缀序列

Pipeline:

1、对所有的后缀从右往左标注 S (smaller) 或 L (larger),  如果一个字母或后缀比他之前的更大则标注为 S ,更小或相等则标注为 L。
2、对于被标注为 S 的前缀,如果其后续字典序更大,则标注为 S* 。
3、将序列 A 分入buckets,buckets的长度取决于出现字符的频次,长度取决于字典序。

Index 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
T i m m i s s i i s s i p p i $
Type S L L S* L L S* S L L S* L L L S*
Buckets $ i m p s

4、将buckets进一步划分入 S- 和 L- buckets, L- buckets在S- buckets的前面。

Index 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
T i m m i s s i i s s i p p i $
Type S L L S* L L S* S L L S* L L L S*
Buckets $ i m p s
Bucket-Typ S L S L L L

5、根据字典序排序 S* 后缀,并将其对应的填入 S- buckets。
5.1 对 S* 的子串进行诱导排序,使用大写字母进行表示,获得文本 T’

Index 1 2 3 4
T’ D B C A
Place in T 4 7 11 15

5.2 递归计算 A’
5.3 输出 A’ ,逆向转换得到排序,并顺序填入对应的Buckets-Typ

Index 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 T i m m i s s i i s s i p p i $ Type S L L

S* L L S* S L L S* L L L S* Buckets $ i m p s Bucket-Typ S L S L L L 15 7 11 4

6. 从左往右遍历 A ,如果在被标记为L,在对应的bucket的顺位中填充A[i] – 1,
7. 从右往左遍历,对对应的S Bucket从右往左填充

Index 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
T i m m i s s i i s s i p p i $
Type S L L S* L L S* S L L S* L L L S*
Buckets $ i m p s
Bucket-Typ S L S L L L
15 7 11 4
14 3 6 10
2 13 5
12 9
8
4
11
1

就。。。老实说吧,我没看懂

function SA-IS(S):
    t = bool[]
    S1 = int[]
    P = int[]
    bucket = int[]
    扫描倒序字符串确定每一个后缀的类型 -> t
    扫描t数组确定所有的LMS子串 -> P
    对所有的LMS子串进行诱导排序
    对每一个LMS子串重新命名,生成新的串S1
    if S1中的每一个字符都不一样:
        直接计算SA1
    else
        SA1 = SA-IS(S1)  # 递归计算SA1
    利用SA1来进行诱导排序,计算SA
    return SA

后缀类型:对每一个后缀suffix(S, i),当suffix(S,i)<suffix(S,i+1)时,是S型后缀。当suffix(S,i) >suffix(S,i+1)时,是L型后缀,对任意的$$i \in [0, \vert{S} -1]$$