后缀数组就是要计算一个数组sa,sa[i]表示排名第i的后缀。可以直接按照后缀做一个快速排序就可以得到sa,但是时间复杂度会是O(nlogn * n)。 (因为要做nlogn次比较,每次比较都是比较两个后缀的大小,需要O(n))
可以利用一个性质:我们让运算符“≤”表示两个串按照字典序比较,然后定义运算符“≤h”表示两个串的前h个字符按照字典序比较(=h、<h等同理),那么就有: 若Aj =h Ak且Aj+h ≤h Ak+h,则Aj ≤2h Ak (j+h, k+h < n,“≤”换成“=、<、>”等等依然成立)
所以,先根据每个后缀的前h个字符排序,然后根据排序的结果,根据每个后缀的前(h=2h)个字符排序。直到h>=n
计算最长公共前缀
height[i]=suffix(sa[i-1])和suffix(sa[i])的最长公共前缀。即height[i]表示排名是i和i-1的最长公共前缀
如果按照直接计算height,由于每次计算height[i],都要比较两个字符串,复杂度为O(n)。所以计算height需要o(n*n)
定义h[i]=height[rank[i]]。 即suffix(i)和排名在suffix(i)前面的后缀的LCP
h[i]有个性质:h[i+1]>=h[i]-1。
证明:
如果h[i]<1,上式必然成立。
如果h[i]>=1
设排名在suffix(i)前面的后缀为k。那么h[i]就是suffix(i)和suffix(k)的LCP。
那么,suffix(k+1) 的排名必然在suffix(i+1)前面。(因为,如果h[i]>=1,所以suffix(i)和suffix(k)的前h[i]个是相同的,suffix(k)的第h[i]+1个字符 必然小于 suffix(i)的第h[i]+1个字符)。 suffix(k+1)和suffix(i+1)的最长公共前缀肯定要大于等于h[i]-1。 所以,suffix(i+1) 与 排名在suffix(i+1)前面的后缀 之间的LCP必然也大于等于h[i]-1。