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;
}