KMP 算法实现 及代码解释

KMP算法就是在一般的比较算法的基础上增加了覆盖因子,避免了每次出现不匹配的时候再从头 开始匹配。

这里所讲匹配因子 即:使得 pattern[0]pattern[1]......pattern[k] = pattern[j-k]pattern[j-k+1]......pattern[j]  中的K。

举例说明:

                 pattern = abcdhjkabcd 

                 可以看出 pattern[0]...pattern[3] = pattern[7]....pattern[10]  ,所以pattern 的覆盖因子为3.

                 同理可得 abcdhjkabc 的 覆盖因子为2.

               但是当 pattern1 = abcehjkabcd 时,其覆盖因子则为-1(假定初始值为-1,一个匹配为0,……以此计),

               而abcehjkabc 的覆盖因子同样为2


覆盖因子的用法,以pattern1示例说明:

              target:abcehjkabcehjkabcd

            pattern:abcehjkabcd

                                       abcehjkabcd 

当红色字体匹配失败时,一般的算法会将pattern会退至字符串开头a,target前进一步,重新进行匹配。这样,效率很低。我们可以很明显的看出匹配成功的字符串中的蓝色字体是重叠的,那么我们可以跳过这部分重叠的部分再做比较,即将pattern向前移动j-overlay[j]。(注:j是匹配失败的字符的下标,overlay[j]即前j个字符的覆盖因子)。

如此便达到了快速匹配的目的。


对于计算覆盖因子可以采用递推的,可以假设pattern的前j个字符

a0a1...ak-1ak=aj-kaj-k+1...aj-1aj
则对于 pattern 的前 j+1 序列字符,则有如下可能
⑴ pattern[k+1]==pattern[j+1]  此时 overlay(j+1)=k+1=overlay(j)+1
⑵pattern[k+1]≠pattern[j+1]  此时只能在 pattern 前 k+1 个子符组所的子串中找到相应的overlay 函数,h=overlay(k),如果此时 pattern[h+1]==pattern[j+1],则 overlay(j+1)=h+1 否则重复(2)过程



上代码(调试通过):

#include "stdAfx.h"
#include <iostream>
#include <vector>
#include <string.h>
#include <stdio.h>
using namespace std;


int kmp_find(const string target,const string pattern)
{
	int patlength = pattern.size();
	int tarlength = target.size();
	int* overlay_value = new int[patlength];
	int indx;
        // 计算覆盖因子 
	overlay_value[0] = -1;
	for (int i=1;i<patlength ;i++)
	{
		indx = overlay_value[i-1];
		while (indx >= 0 && (pattern[i]!= pattern[indx+1]))
			indx = overlay_value[indx];
	    if(pattern[i]== pattern[indx+1])
			overlay_value[i] = indx +1;<span style="white-space:pre">	</span>
		else
			overlay_value[i] = -1;
	}

	int tarIndx = 0;
	int patIndx = 0;
        
       //
	while((tarIndx < tarlength) && (patIndx < patlength ))
	{
		if(target[tarIndx] == pattern[patIndx])
		{
			++tarIndx;
			++patIndx;
		}
		else if (patIndx == 0) //避免出现下表为-1的情况
		{
			++tarIndx;
		}
		else
		{
			patIndx = overlay_value[patIndx-1]+1;
		}
	
	}
    if(patIndx == patlength)
		return 1;
	return -1;
}







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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值