SA后缀数组总结

SA后缀数组用于字符串。首先把每一个位置对应的后缀字符串按字典序从小到大排序,然后设sa[i]表示排名为i的后缀串在原串中对应的位置,rank[i]表示原串中位置i对应的后缀的排名为i。

接下来讲讲怎样求sa。这里主要运用了倍增的思想。

设S[i,k]表示从i开始长度为k的字符串在所有长度为k的字符串中的排名,一开始我们先求出S[i,1]。接下来我们考虑利用S[i,1]来求S[i.2]。

这要用到一条性质:设现在有字符串A,B,C,D,若有AB,则有AC>BD。若A与B相等,则比较C、D的大小。总之,我们可以通过两个字符串前半部分的大小关系与后半部分的大小关系来求出它们的大小关系。

于是,我们把S[1,1]与S[2,1]拼起来就得到了S[1,2],S[2,1]与S[3,1]拼起来就得到了S[2,2],以此类推。然后我们可以利用S[1,1],S[2,1],S[3,1]…之间的大小关系推出S[1,2],S[2,2]…之间的大小关系(用快排以第一关键字和第二关键字的形式排序)。接着,我们又可以利用S[i,2]来推出S[i,4]。

就这样,我们每次把S[i,k]与S[i+k,k]拼接起来得到S[i,2k],最后就可以求出sa了。求出了sa之后rank[sa[i]]=i。

注意,在i+k>n时我们就把S[i+k,k]按0算。这个过程一直做到当k>n时停止。若中间的排序用快排则效率是O(nlog^2n),若用基数排序则效率是O(nlogn),但是我不会。

接着来讲一讲height数组。设height[i]表示排名i的后缀与排名i-1的后缀的最长公共前缀的长度(height[1]=0)。

为了求height,我们在多设一个h,h[i]=height[rank[i]]。有一条十分重要的性质就是h[i]>=h[i-1]-1,证明如下:

      设a[k...n]是排在a[i-1...n]的后缀,它们的最长公共前缀的长度为h[i-1],则在去掉了它们的第一位之后,也就是串a[k+1...n]        一定排在串a[i...n]的前面。而因为之前a[k...n]与a[i-1...n]的最长公共前缀为h[i-1],所以再去掉了以为之后它们的最长公共前        缀至少为h[i-1]-1。证毕。

有了这一条性质,我们就可以用O(n)的效率求出h(每次从h[i-1]-1开始枚举比较是否相同),进而求出height。

有关SA后缀数组的知识就差不多写完了,至于具体应用,因为我还没有做过多少题,所以没用总结,以后再补。

你可能感兴趣的:(算法)