算法之1--KMP

                   KMP,即The Knuth-Morris-Pratt Algorithm,中间的单词是创造早这个算法的三个人,该算法可以用于字符串的匹配查找,该算法的优势体现在当主串和模式串有重复字符时,可以降低时间复杂度。一般在学习算法之前所用的方法的方法都是暴力求解(Brute Force,BF),下面我将一一讲解这两种算法。

 一.BF

先不说介绍,先看查找过程,如下图:


这边p从M的第一位开始比较,第一位满足,接着进行第一位......五位的比较,发现第六的时候并不满足,这时,开始M的第二位与P的第一位开始比较,如图:


发现M[1]与P[0]并匹配,于是M的下标开始移动。。。。就这样一直遍历,直到在M中找到了连续的与P长度相等并相匹配的字符串。

2.KMP

2.1  NEXT数组

KMP我觉得最关键的是求得它的next的数组,所谓next数组,next[i]表示i位之前的字符前缀与后缀最大的匹配数,以abiabc,next[3]=0,注意:这边的后缀不是从a开始的,是a之前的,所以应该是i开始的,如果从a开始得到1,是错误的。依据正确的算法,得到下面的next值,由于o之前没有元素,设next[0]=-1:


2.2 KMP之于BF的改进和查找模式


KMP与BF的查找(或者说改进)是,以上图的BF比较为例:     

当比较到P的第六位的时候,BF会将M[1]与p[0]进行比较,而KMP则会先算出next[j]的值,这边j=5,next[5]=2,所以此时M[i]的i=5,p会将移动next[5]的长度,即2

个长度两者进行比较,这样减少了时间复杂度.此时比较的情况如图:


此时进行比较的是M的D和P的I,同时我们也发现i之前的两位与D之前的两位是相同的,a,b就是next【5】可以求出的可以移动的那两位。

3.代码

上面的是理论的,接下来就是代码的部分了,所使用的是java语言。下面是求next的部分。。

private static int[] nextcal(char[] pattern) {
		//初始化next[0]的值
	    //定义两个变量,i,j分别表示模式串的开头,结尾
	    int i=-1;
	    int j=0;
	   //模式串的长度,用来控制结束时间
		int pattern_len=pattern.length;
		int next[]=new int[pattern_len];
	   //初始化next[0]的值
	    next[0]=-1;
		//从next[0]开始赋值
		while(j<pattern_len-1)
		{
			//pattern[i],pattern[j]分别表示第j个字符额前缀和后缀
			//i=-1表示未找到前缀与后缀相等,i即next【j-1】
			if(i==-1 || pattern[i]==pattern[j])
			{
				i++;
				j++;
				next[j]=i;
			}else
			{
				i=next[i];
			}
		}		
		return next;
	}

总结,关键是怎么求出next数组的值,还有kmp运用的限制条件,以及-1的使用

附:完整代码:欢迎关注我的github账号:chunrong918









  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值