【定义】
【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