最长公共前缀LCP

需要预先知道的:
sa数组,其中按照数组的顺序存放着按照字符串后缀排好序的该后缀的首字符位置

rank数组,其中rank[i] = i在sa中的排名

因此sa和rank是两个互逆的数组,即sa[rank[i]] = i;

此外也可以直观表示为sa[排名] = 首字符位置,rank[位置] = 排序后的排名

height数组,height[i] = suffix(sa[i-1], sa[i]);

 

定理1:对于rank[j] < rank[k],则后缀Sj...n 和Sk...n的LCP可以表示为min{height[rank[j] + 1], height[rank[j] + 2], ... , height[rank[k]]}

举蓝书中的例子:

显然这是成立的,因为sa数组是已排好序的后缀。

因为是按照字典序排的,所以假设s1, s2, s3是sa中的连续三个后缀, 那么lcp(s1, s3) 即 min{lcp(s1, s2), lcp(s2, s3)},这具有传递性。

 

现在我们已知sa数组,rank[sa[i]] = i, 近乎O(n)复杂度求height数组

void getHeight()
{
    for(int i = 1; i <= n; i++) rank[sa[i]] = i;
    
    int k = 0;
    for(int i = 1; i <= n; i++){
        if(k) k--;
        int j = sa[rank[i] - 1];
        while(s[i + k] == s[j + k]) k++;
        height[rank[i]] = k;
    }
}

这里需要提及这里有一个辅助数组h[i] = height[rank[i]]

h[i] >= h[i - 1] - 1

这里我们仍然用紫书上的证明:

以上就是LCP的基本操作了,待补其他

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值