前缀数组:height数组,height[i]=suffix(sa[i-1])和suffix(sa[i])的最长公共前缀,也就是排名相邻的两个后缀的最长公共前缀。
它有以下两个性质:
1:对于i和j,假设有rank[ i ]<rank[ j ],那么rank[ i ]同rank[ j ]的相同的前缀数是height[rank[i]+1],height[rank[i]+2], height[rank[i]+3],……, height[rank[j]]中的最小值。
2:定义h[i]=height[rank[i]],也就是suffix(i)和在它前一名的后缀的最长公共前缀。那我们有h[i]≥h[i-1]-1。
证明:设suffix(k)是排在suffix(i-1)前一名的后缀,则它们的最长公共前缀是h[i-1]。那么suffix(k+1)将排在suffix(i)的前面(这里要求h[i-1]>1。如果h[i-1]≤1,原式右边小于等于0,显然成立)并且suffix(k+1)和suffix(i)的最长公共前缀是h[i-1]-1,所以suffix(i)和在它前一名的后缀的最长公共前缀至少是h[i-1]-1。
如图,因为suffix(i)与suffix(i-1)排名不一定相邻,又因为排名相邻的两个后缀拥有的前缀是最多的(即多于h[i]),所以h[i]一定会大于等于h[i-1]-1。
按照h[1],h[2],……,h[n]的顺序计算,并利用h数组的性质,时间复杂度可以降为O(n)。
代码:
void get_height(int n)
{
int k=0;
for(int i=1;i<=n;i++)
{
int j=sa[rank[i]-1];
if(k) k--;//k表示height[rank[i]-1]的值,即h[i-1]
while(a[i+k]==a[j+k]) k++;
height[rank[i]]=k;
}
}
推荐:《后缀数组—sa与rank》http://blog.csdn.net/a_bright_ch/article/details/53454088