码迷,mamicode.com
首页 > 编程语言 > 详细

后缀数组

时间:2020-06-19 21:10:49      阅读:59      评论:0      收藏:0      [点我收藏+]

标签:后缀数组   情况   math   ref   获得   字典序   处理   emma   limits   

后缀数组

对于给定的字符串\(s\),构建两个数组\(sa\)\(rk\),其中\(rk[i]\)表示\(s[i,n]\)\(s\)的所有后缀中的字典序排名,\(sa[i]\)则表示排名\(i\)的后缀的最左端位置。容易发现有\(sa[rk[i]]=rk[sa[i]]=i\)

构造 - 倍增法

一般来说,我们用倍增法\(O(n\log n)\)构建出\(rk\)数组就可以了。

我们倍增考虑的长度\(k\)。当\(k>=n\)时退出。

  • 每次倍增开始前,你要保证这些后缀的排名是将他们“长度为\(k\)的前缀”排序后的排名。若两个字符串“长度为\(k\)的前缀”相同,则排名也应相同。
  • 然后把每个后缀\(i\)“以\(rk[i]\)为第一关键字、\(rk[i+k]\)为第二关键字”再次排序,更新\(rk\)数组。(对于越界的\(rk\)下标,你认为其值为\(-\infty\))这样你就得到了按“长度为\(2k\)的前缀“排序后的排名辣!

最开始时把所有后缀按它们的首字母排序,获得初始排名\(rk\)数组即可。

排序过程采用基数排序,则总复杂度为\(O(n\log n)\)

举个栗子:

b a n a n a
2 1 3 1 3 1 // k=1
3 2 4 2 4 1 // k=2
3 2 5 2 4 1 // k=4
4 3 6 2 5 1 // k=8

用途 - LCP(最长公共前缀)

我们令\(lcp(s_1, s_2)\)为字符串\(s_1, s_2\)的最长公共前缀。令\(LCP(i,j)=lcp(s[sa[i],n], s[sa[j],n])\)

那么我们有引理\(LCP-Lemma\)\(\forall i<j<k, LCP(i,j)=\min(LCP(i,j),LCP(j,k))\)

这样我们就得到了推论:\(LCP(i,j)=\sum\limits_{k=i+1}^j LCP(k-1,k)\),原问题转为\(RMQ\)。但不幸的是,\(LCP(k-1,k)\)你还只会\(O(n^2)\)预处理,这显然是不行的。

height 数组

我们设\(height[i]=LCP(i,i-1), h[i]=height[rk[i]]\),则\(height[1]=0\)。考虑如何高效求\(h\)数组。

有一个结论\(LCP-Theorem\)\(h[i]\ge h[i-1]-1\)

根据\(LCP-Theorem\),每次\(h[i]\)直接从\(h[i-1]-1\)开始大力枚举就好。复杂度\(O(n)\)

再举一个栗子:

s: b a n a n a
h: 0 3 2 1 0 0

a -> 0
ana -> 1
anana -> 3
banana -> 0
na -> 0
nana -> 2


引理及证明


引理LCP-Lemma

\(\forall i<j<k, LCP(i,j)=\min(LCP(i,j),LCP(j,k))\)

证明:设\(p=\min(LCP(i,j),LCP(j,k))\),则我们显然有\(p\ge LCP(i,k)\)

结合\(i<j<k\),我们可以知道:\(s[sa[i]+p]<s[sa[j]+p]\)\(s[sa[j]+p]<s[sa[k]+p]\)中至少一个成立。否则\(p<\min(LCP(i,j),LCP(j,k))\)并产生矛盾。
所以\(s[sa[i]+p]<s[sa[k]+p]\),故\(p\le LCP(i,k)\)。证毕。


定理LCP-Theorem

\(h[i]\ge h[i-1]-1\)

证明:当\(h[i-1]=0\)时,显然成立。下面讨论\(h[i-1]>0\)的情况。

\(k=sa[rk[i-1]-1]\),则\(h[i-1]=lcp(s[k,n], s[i-1,n])\),那么有\(\left\{\begin{array}{**lr**} h[i-1]-1=lcp(s[k+1,n], s[i,n])\\ rk[k+1]<rk[i] \end{array}\right.\)(这一步相当于把他们的首字符砍掉)。

结合\(LCP-Lemma\),可得

\[\begin{aligned} &lcp(s[k+1,n], s[i,n])\&=LCP(rk[k+1], rk[i]) \&= \min(LCP(rk[k+1], rk[i]-1), LCP(rk[i]-1, rk[i]))\end{aligned} \]

\(lcp(s[k+1,n], s[i,n])\le LCP(rk[i]-1, rk[i])\)

\(h[i-1]-1\le h[i]\),证毕。

后缀数组

标签:后缀数组   情况   math   ref   获得   字典序   处理   emma   limits   

原文地址:https://www.cnblogs.com/skiceanAKacniu/p/13166341.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!