倍增算法实现后缀数组详解+实现代码

【前言】

不要被文章的长度吓到,因为罗穗骞的论文要更长更详尽,我只是取了其中的一部分进行学习并做一个学习笔记,便于以后有需要的时候回顾。文章的内容主要是介绍后缀数组的实现,后缀数组的应用部分主要是结合例题来理解。

目录

【后缀数组】

【引入】

【后缀数组的实现】

【倍增算法】

【具体实现】

【步骤解析】

【复杂度分析】

【后缀数组的应用】

【最长公共前缀】

【单个字符串的相关问题】

【两个字符串的相关问题】

【多个字符串的相关问题】

【完整代码】

【内容来自】


【后缀数组】

       

【引入】

AC自动机可以解决多模板匹配问题,但前提是事先知道所有的模板。在实际应用中,很多时候都是无法事先知道查询的,这时需要预处理文本串T,而不是模式串。

假定文本串为BANANA,可以在它的末尾加一个字符$(代表一个没在串中出现过的字符),然后把它的所有后缀(BANANA$,ANANA$,NANA$,ANA$,NA$,A$)插入到一棵Trie中(前置知识:字典树详解),如下图所示:

有了这个后缀Trie,查找一个长度为m的模板时只需要进行一次普通Trie查找,时间复杂度为O(m)。

在实际运用中,会把后缀Trie中没有分支的链合并到一起,得到所谓的后缀树(suffix tree),但由于后缀树的构造算法比较复杂难懂且容易写错,因此我们就需要用到后缀数组。后缀数组是后缀树的替代品,具有容易编程实现,占用内存空间小,且能够实现后缀树的很多功能而时间复杂度也并不逊色的特点。

在绘制上图时,我们需要把所有后缀按字典序从小到大排序,也就是说,我们需要把每个结点的所有子结点排好序,字典序小的在左边(规定$比所有其他字符都小),然后每个叶结点里标上该后缀首字符的下标。比如后缀NA开始于BANANA的下标4(注意下标从0开始),那么NA对应的叶结点标有"4"。为了方便描述,我们把“以下标k开头的后缀”表示为Suffix(k),也就是说,对于文本串BANANA,Suffix(4)就是NA。

现在只需自左向右把所有叶子的编号排列出来,就可以得到后缀数组(suffix array)

比如,BANANA的后缀数组SA[]={5,3,1,0,4,2}。

名次数组Rank[i]:保存的是Suffix(i)在所有后缀中从小到大排列的“名次”。

简单的说,后缀数组是“排第几的是谁?”,名次数组是“你排第几?”。容易看出,后缀数组和名次数组为互逆运算。

【后缀数组的实现】

根据定义,后缀数组可以直接通过一次快速排序得到,但是在最坏情况下,直接排序需要的时间是O(n^2logn)(虽然比较次数是O(nlogn),但是两个字符串的比较是O(n)的)。下面介绍后缀数组的两种实现方法:倍增算法DC3算法

【倍增算法】

主要思想:用倍增的方法对每个字符开始的长度为2^k的子字符串进行排序,求出排名,即rank值。k从0开始,每次加1,当2^k大于n以后,每个字符开始的长度为2^k的子字符串便相当于所有的后缀。并且这些子字符串都一定已经比较出大小,即rank值中没有相同的值,那么此时的rank值就是最后的结果。每一次排序都利用上次长度为2^{k-1}的字符串的rank值,那么长度为2^{k}的字符串就可以用两个长度为2^{k-1}的字符串的排名作为关键字表示,然后进行基数排序,便得到了长度为2^{k}的字符串的rank值。以字符串“aabaaaab”为例,整个过程如下图所示。x、y表示长度为2^{k}的字符串的两个关键字。

【具体实现】

int wa[maxn],wb[maxn],wv[maxn],ws[maxn];
int cmp(int *r,int a,int b,int l)
{return r[a]==r[b]&&r[a+l]==r[b+l];}
void da(int *r,int *sa,int n,int m) //n为字符串的长度加1,因为在使用倍增算法前在原字符串后面加一个0
{
    int i,j,p,*x=wa,*y=wb,*t;
    for(i=0;i<m;i++) ws[i]=0;
    for(i=0;i<n;i++) ws[x[i
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值