KMP算法的理解

什么是KMP算法?

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

假设当前正在比较的字符是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];  
        }  
    }  
}  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值