KMP算法学习

KMP算法是一种高效的模式匹配算法。

 

与BF算法的比较

        在普通的匹配算法BF中,目标串和模式串的索引值都需要重新回到起点再次进行匹配,所以该算法的时间复杂度较高,达到O(m*n)。KMP算法的核心思想是寻找模式串本身的特征,在此基础上达到目标串不回溯,模式串有规律回溯的目的,以减少回溯比较的次数,降低时间复杂度,达到O(m+n)。但是这是建立在提高空间复杂度的基础上的。

        BF算法:时间复杂度O(m*n);空间复杂度O(1)

        KMP算法:时间复杂度O(m+n);空间复杂度O(n)

 

KMP算法核心

       KMP算法的核心是寻找模式串本身的规律。在该算法中表现为反映该规律的next数组。next数组的作用是在每次失配时,模式串根据next数组对应位置上的值回溯模式串索引的位置。next数组的求法也是KMP算法的精华所在。在本文的参考博文[1]和参考博文[2]中均给出了next数组的具体求法,但是遗憾的是在[1]中,并没有给出next数组的具体含义,而[2]中给出了具体的next定义。

      next数组有如下定义:

      (1) next[j]=-1    j=0

      (2) next[j]=max ( k ):     0<k<j    P[0...k-1]=P[j-k,j-1]

      (3) next[j]=0    其他

      该定义的意义就是next数组的首位均为-1。在其他位置上,该位置之前的子串中最长的相同前后缀长度(注释1)。当没有任何相同的前后缀的情况下,next值为0。

      注释1:前后缀的含义,例如在a b c a b中,前缀和后缀均为"ab"。

     

next数组的计算方法

      由next数组的定义可知,可以用一种递推的思想来求解next数组。

      根据定义next[0] = -1

      假设next[j] = k, 即P[0...k-1] == P[j-k,j-1]

      (1)若P[j] == P[k],则有P[0..k]==P[j-k,j],很显然,next[j+1]=next[j]+1=k+1;

      (2)若P[j] != P[k],则可以把其看做模式匹配的问题,即匹配失败的时候,k值如何移动,显然k=next[k]。

 

代码实现:

     求next数组

void get_next(const char* ptrn,int* nextval)
{
	int plen = strlen(ptrn);

	int i = 0;
	int k = -1;
	nextval[i] = -1;

	while(i < plen -1)
	{
		if (k == -1 || ptrn[i] == ptrn[k])
		{
			++i;
			++k;
			nextval[i] = k;
		}
		else
		{
			k = nextval[k];
		}
	}
}

 

    KMP算法

int KMP_search(const char* src, const char* ptrn, const int *nextval )
{
	int i=0;
	int j=0;
	int slen = strlen(src);
	int plen = strlen(ptrn);

	while(i<slen && j<plen)
	{
		if (j == -1 || src[i] == ptrn[j])
		{
			i++;
			j++;
		}
		else
		{
			j = nextval[j];
		}
	}

	if ( j >= plen)
	{
		return i - plen;
	}
	else
	{
		return -1;
	}
}


 

参考博客[1]:http://blog.csdn.net/v_july_v/article/details/7041827

参考博客[2]:http://www.cnblogs.com/dolphin0520/archive/2011/08/24/2151846.html

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值