需要预先知道的:
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的基本操作了,待补其他