您的位置:首页 > 其它

KMP算法的理解

2014-11-08 23:15 274 查看
什么是KMP算法?

模式串 char[] pat = new char[M]; 文本串 char[] txt = new char
;

假设当前正在比较的字符是txt[i]和pat[j], 即pat[0, j - 1]已经匹配成功。txt[i]后面的字符处于未知状态。



pat[j]之前的子字符串的最长相同前缀后缀的长度为k,即pat[0, k -1] 与pat[j – k, j – 1]依次在对应位上相等。



如果匹配失败,则下一次比较的字符对是txt[i]和pat[k]。

可以看出,向右移动了j - k位。如果按照暴力查找法,则只会移动1位。

next[]数组的求解?

下面分析一下如果已知next[j]=k,如何推导出next[j+1]。

求next[j+1]就是求字符串pat[0,j]的最长前缀后缀的长度。

1. 如果pat[k]==p[j],则next[j+1] = next[j] + 1 = k + 1;



1. 如果pat[k]≠p[j],暂时还不能确定,需进一步判断。记next[k]的值为m,若pat[m] == pat[j],则next[j+1] = m + 1;否则继续递归前缀索引k = next[k],而后重复此过程,直到m=-1,表示匹配失败,next[j+1] = 0。

记,如下图。



注:

若next[k]=m, 则:

pat[0,m-1] = pat[k-m,k-1];

再根据next[j]=k,则

pat[k-m,k-1] = pat[k-m + (j-k),k-1+(j-k)] = pat[j-m,j-1],

从而得出结论:

pat最前面的m个字符和索引j之前的m个字符依次相等。

附求Next数组的代码:

void GetNext(String p,int[] next)
{
int pLen = strlen(p);
next[0] = -1;
int k = -1;
int j = 0;
while (j < pLen - 1)
{
/*循环起始,k的值是子串a[0,j-1]的最大前缀后缀长度,即next[j];为了计算a[0,j]的最大前缀后缀长,需要先比较a[j]和a[k],如果:
1.相等,则next[j+1] = k++,求解完毕。同时j++,准备下一次循环;
2.不相等,则让p[next[k]]再和p[j]比较:若
2.1 相等,则next[j+1]就是next[k]+1,求解完毕。同时j++,准备下一次循环。
2.2 不相等,则next[k]再往下迭代,
。。。
直到碰到next的值是-1时停止,表示匹配失败。
*/
if (k == -1 || p.charAt(j) == p.charAt(k))
{
++k;
++j;
if(p.charAt[j] != p.charAt(k)){
next[j] = k;
}else {
next[j] = next[k];
}
}
else
{
k = next[k];
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: