后缀数组学习笔记 - 更新ing

后缀数组

定义:

1.后缀i:字符串从第i位到最后一位的字串,如’abcd’的 后缀3 为 ‘cd’
2.suffix[i]:表示后缀i。对于字符串’ABABCDDD’有
在这里插入图片描述
3.sa[i]:(对这些后缀排序后)排名第i的后缀排序前的排名
在这里插入图片描述
4.rank[i]:第i个后缀排序后的排名。
在这里插入图片描述
5.height[i]:(排序后)第i-1个后缀和(排序后)第i个后缀的最大公共前缀,如 ‘DDD’ 和 ‘DD’,最大公共前缀长度即为 2。

性质:

1.若rank[i] = sa[j]则sa[i] = rank[j],rank[sa[i]] = sa[rank[i]] = i
2.如果rank[j]<rank[k],则suffix[j]和suffix[k]的最大公共前缀长度 等于 min ⁡ { h e i g h t [ r a n k [ j ] + 1 ] , h e i g h t [ r a n k [ j ] + 2 ] , . . . , h e i g h t [ r a n k [ k ] ] } \min \{height[rank[j]+1],height[rank[j]+2],...,height[rank[k]]\} min{height[rank[j]+1],height[rank[j]+2],...,height[rank[k]]}
3. h e i g h t [ r a n k [ i ] ] ≥ h e i g h t [ r a n k [ i − 1 ] ] − 1 height[rank[i]]≥height[rank[i−1]]−1 height[rank[i]]height[rank[i1]]1

证明

1.略
2.假如suffix[i]和suffix[j],有rank[i]<rank[j],设它们的最大公共前缀为 sa(i,j),即字符串suffix[i]和suffix[j]前sa(i,j)位是相等的,且从第sa(i,j)+1位开始不相等。
对于rank[i] +1 = rank[j],显然成立。
对于rank[i] +1 < rank[j]的情况,中间字符串的大小介于它俩之间,第sa(i,j)位及之前肯定都是相等的,sa(i,j)+1位的转变肯定是在其中某两个字符串上发生的,所以也必然成立。

3.若排序后suffix[k-1]刚好排在suffix[i-1]前面,且它们的最小前缀为height[rank[i-1]]且不为0。
此时必定满足suffix[k]刚好排在suffix[i]前面,且它们的最小公共前缀 height[rank[i]] 正好为 height[rank[i-1]]-1
如果height[rank[i-1]] = 0,显然也成立。

求取rank和sa

算法原理

有一种类似于基数排序的方法。
以aaabcda为例子
①先把 n 位分成 n 个字符,放在一个数组里,求出每个字母的排名 ①先把n位分成n个字符,放在一个数组里,求出每个字母的排名 先把n位分成n个字符,放在一个数组里,求出每个字母的排名
在这里插入图片描述

②设 i 为 0 ,把每一个字符,加上后面的第 2 i − 1 个字符形成一个小字符串,用排名数字代替字母后,再次排名,得到每一个子串的排名 ② 设 i 为 0,把每一个字符,加上后面的第 2^{i-1} 个字符形成一个小字符串,用排名数字代替字母后,再次排名,得到每一个子串的排名 i0,把每一个字符,加上后面的第2i1个字符形成一个小字符串,用排名数字代替字母后,再次排名,得到每一个子串的排名
在这里插入图片描述

③令 i + 1 ,把字符串看成一个新的字符,继续执行②,直到 1 + 2 i − 1 > n ,即可得到 n 个后缀子串的排名,即 r a n k 和 s a ,实际求取的时候全程用数字代替字符,免去字符长度带来的复杂度 ③令i+1,把字符串看成一个新的字符,继续执行②,直到1+2^{i-1}\gt n,即可得到n个后缀子串的排名,即rank和sa,实际求取的时候全程用数字代替字符,免去字符长度带来的复杂度 i+1,把字符串看成一个新的字符,继续执行,直到1+2i1>n,即可得到n个后缀子串的排名,即ranksa,实际求取的时候全程用数字代替字符,免去字符长度带来的复杂度
在这里插入图片描述
每次取后面第 2 i − 1 个字符,为的就是能够拼出完整且正确的后缀 每次取后面第2^{i-1}个字符,为的就是能够拼出完整且正确的后缀 每次取后面第2i1个字符,为的就是能够拼出完整且正确的后缀

代码实现

在这里插入代码片
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值