扩展的KMP算法,这个算法作为KMP的扩展,可以说是包含KMP的。它求出了一组数值,extend[i]表示A串中以i开始的后缀(从i到lena的子串)与B串的最长公共前缀(从头数到不一样的字符)的长度,也就是LCP。next[i]表示T[i..m]与T的最长公共前缀长度,也就是自匹配的长度。设extend[0..k-1]已经算好,并且在以前的匹配过程中到达的最远位置是p-1。最远位置严格的说就是i+extend[i]-1的最大值,其中i=0,1,2,3,…,k-1;设取最大值的i是a。则有A[a~p-1] == B[0~p-a-1],可以推出有A[k~p-1] == B[k - a ~ p -1 - a] , 令L = next[k-a],若k+L<p,则extend[k]=L, 否则继续判断A[p]和B[p-k],直到不相等,这时需要更新extend[k]和a值。原理上如果说不明白的话可以看看代码:
void build_next()
{
int k, q, p, a;
next[0] = len_t;
for (k = 1, q = -1; k < len_t; k ++, q –) {
if (q < 0 || k + next[k - a] >= p) {
if (q < 0)q = 0, p = k;
//q是B串继续向后匹配的指针,p是A串继续向后匹配的指针,也是曾经到达过的最远位置+1
//q在每次计算后会减小1,直观的讲就是B串向后错了一位
while (p < len_t && T[p] == T[q]) {
p ++, q ++;
}
next[k] = q, a = k;
}
else {
next[k] = next[k - a];
}
}
}
void extend_KMP()
{
int k, q, p, a;
for (k = 0, q = -1; k < len_s; k ++, q –) {
if (q < 0 || k + next[k - a] >= p) {
if (q < 0)q = 0, p = k;
while (p < len_s && q < len_t && S[p] == T[q]) {
p ++, q ++;
}
extend[k] = q, a = k;
}
else {
extend[k] = next[k - a];
}
}
}
同样是线性的复杂度
来自Gobbin Path,小驴博客的文章
本文地址:http://gobbin.cn/archives/594