KMP算法

概念

       KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt同时发现,因此人们称它为克努特——莫里斯——普拉特操作(简称KMP算法)。KMP算法的关键是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是实现一个next()函数,函数本身包含了模式串的局部匹配信息。时间复杂度O(m+n)。

算法思路

1、主串不需要回滚

2、子串通过子串本身的一种性质,调整j的位置,再继续与i比较

3、时间复杂度由暴力破解的O(m*n)提高到O(m+n)

解题思路

1、如果是只需要理解(做选择题啊什么的)

      首先我们要明白三个单词的意思:

             前缀:指的是必须包含第一个字符,但是不包含最后一个字符的字符组。

             后缀:指的是必须包含最后一个字符,但是不包含第一个字符的字符组。

             next:每个串对应的最大的相同值。

 

  现在的next数组失配时是用前一个匹配的位置找对应的j的新位置,但是算法要求是当前位置找对应的新位置。

 所有直接将原next数组整体右移一位,next[0]定义成-1,如下图:

我们再来看个串匹配的例题:

下面是串匹配的步骤:

这样我们的值就匹配完成了,对于我们平时做题,如果是选择题,那么答案就出来了,但是一般都是会要求我们写出源码。这时候,我们就要进行更深层次的理解。

2、编码

首先我们要理解next[j],它既是最大前缀或后缀值,也是跳到的数组下标。

(1)设置j指向前缀,i遍历子串,指向后缀(其实也就是看作是主串和子串是一样的匹配过程)

(2)如果p[i]==p[j]或者j==-1相等则,i++;j++;next[i]=j(再次注意,j是下标的同时,也是最大前缀者)

(3)如果p[i]!=p[j],j=next[j];如果p[j]与p[i]还是不相等,继续循环跳next[j]

核心代码:

public static int[]getNext(char[]p){
	int[]next=new int[p.length];
	next[0]=-1;
	int j=0;
	int i=1;
	
	while(i<p.length-1) {
		if(j==-1||p[i]==p[j]) {
			++j;
			++i;
			next[i]=j;
		}else {
			j=next[i];
		}
	}
	return next;
}
public int kmp(char str[],char p[],int next[]) {
	int i=0,j=0;
	int n=str.length;
	int m=p.length;
	for(i=0;i<n;++i) {
		while(j>-1&&str[i]!=p[j]) {
			j=next[j];
		}
		if(j==-1||str[i]==p[j]) {
			j++;
		}
		if(j==m) {
			return i-j+1;
		}
	}
	retrun -1;
}

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值