算法学习:后缀数组 height的求取

时间:2019-08-25
本文章向大家介绍算法学习:后缀数组 height的求取,主要包括算法学习:后缀数组 height的求取使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

【定义】

【LCP】全名最长公共前缀,两个后缀之间的最长前缀,以下我们定义

lcp ( i , j ) 的意义是后缀 i 和 j 的最长前缀

【z函数】 函数z [ i ] 表示的是,第 i 个后缀和字符串的最长前缀


 【解决问题】

这两个算法都是在解决这个问题

即求后缀和字符串和后缀之间的最长公共前缀

但是有所不同的是,

后缀数组最终求出的是,字典序第 i 个后缀和第 i + 1 个后缀的最长公共前缀

z函数最终求出的是,第 i 个后缀和字符串的最长公共前缀

然后通过这个最长公共前缀求一些其他的值


【算法学习】

【后缀数组】

  后缀数组能够在 n 的时间内求出字典序第 i 和第 i - 1 个后缀的最长公共前缀

  而这个函数通常被命名为 height 

  height [ i ] 的含义为 , 字典序第 i - 1个后缀和第 i 个后缀的最长公共前缀

  有以下几个性质进行求取:(s [ i ] 表示第 i 个后缀)

  1.若 i 小于 j , LCP ( i , j )  = min { LCP ( k - 1 , k ), i + 1 <= k <= j }

  可利用此项用 RMQ 求LCP

  2.定义 h [ i ] 为 :第 i 号开始的后缀和他字典序前面的后缀的LCP

  即: h [ i ] = height [ rank [ i ] ]

  于是有,对于 i > 1 且 rank [ i ]  > 1 有  

   h [ i ]  >  h [ i - 1 ] - 1 ;

   

  证明如下 :

  设 j 为 第 i - 1 号开始的后缀按排名的前面的那个后缀的开始的位置

  注意: j 不是第 i - 2号

  此时,第 j 个后缀和第 i - 1 个后缀的 LCP 在定义上为 height [ rank [ i - 1 ] ],即 h [ i - 1 ]

  即我们要证明的右半部分的一部分

  然后我们讨论 j + 1 和 i (由得到 i - 1 + 1 ) 的关系:

  第一种,当 j 和 i - 1 首字母不相等的情况,h [ i - 1 ] 为 0

  那么显然  h [ i ] > h [ i - 1 ] - 1

  第二种,当 j 和 i - 1 首字母相等的情况,  

  那么显然,j 和 i - 1 的 LCP 为 h [ i - 1 ] - 1

  在后缀中,排名比 i 考前,和后缀 i LCP最长的,相似度最高的显然是SA中离他最近的那个

  即 SA [ rank [ i - 1] ]  - 1 

  也就是 , h [ i ] >= h [ i - 1 ] - 1

  证毕

  

  所以我们每次找最长前缀的时候,都可以从 h [ i - 1 ]  开始检索

  可以类比 manacher

  代码如下:

void GetHeight() {
    int j, k = 0;
    for(int i = 1; i <= N; i++) {
        if(k) k--;
        int j = sa[rak[i] - 1];
        while(s[i + k] == s[j + k]) k++;
        Height[rak[i]] = k;
        printf("%d\n", k);
    }
}

题目:

【SDOI 2008】 Sandy的卡片

  

原文地址:https://www.cnblogs.com/rentu/p/11338901.html