后缀数组——height数组

说明:本文主要讲述后缀数组中的height数组,写后缀数组的一些题目时,发现大部分都要用到height数组,最长公共前缀就是height数组能求解的众多问题之一,本文通过对最长公共前缀的求解来讲述height数组,关于后缀数组的构造问题看这里:后缀数组的构造

最长公共前缀(Longest Common Prefix)

题目描述:给定一个字符串,求该字符串后缀a和后缀b的最长公共前缀

定义height[i]=k:表示后缀Sa[i]和后缀Sa[i-1]的最长公共前缀的长度为k

定义LCP(a,b):表示后缀a和后缀b的最长公共前缀的长度

对于后缀a和后缀b的最长公共前缀(不妨设Rank[a]

LCP(a,b)=min(height[ Rank[a] ]、height[ Rank[a]+1]、height[ Rank[a]+2]、……、height[ Rank[b] ])

这也就转化成了求height数组在区间[Rank[a],Rank[b] ]上的最小值,这就是经典的RMQ问题,可用树状数组或线段树解决,所以现在我们只要求出height数组即可

例如:字符串为"aabaaaab",求后缀"abaaaab"和后缀"aaab"的最长公共前缀,如图4所示:

后缀数组——height数组_第1张图片

如何快速求出height数组呢?

定义h数组:h[i] = height[ Rank[i] ] ;我开始一看这形式心态就崩了,这是什么意思啊!!!然后我就一步步地推才明白h[i]其实是表示"后缀i"和"后缀i前一个后缀z"的最长公共前缀的长度(这里的"前一个后缀"指后缀排序后,后缀i的前一个后缀)

h[i] = LCP(Sa[ Rank[i] ],Sa[ Rank[i]-1])=LCP( i,Sa[ Rank[i]-1])=LCP(i,z)(z满足:Rank[z] = Rank[i] -1)

则h数组有这样的性质:h[i]\geq h[i-1]-1

证明:

如果h[i-1]<=1,则h[i]\geq h[i-1]-1恒成立

所以考虑h[i-1]=k(k>1)时:

后缀数组——height数组_第2张图片

具体实现的时候其实没有必要保存h数组,只须按照h[1],h[2],……,h[n]的顺序计算即可,计算height数组C++代码实现:

void get_height()
{
    int k=0;
    for(int i=1;i<=n;i++)
    {
        if(k)
            k--;
        int j=Sa[Rank[i]-1];
        while(str[i+k]==str[j+k])
            k++;
        height[Rank[i]]=k;
    }
    return ;
}

 

你可能感兴趣的:(数据结构)