您的位置:首页 > 其它

理解KMP算法

2016-07-21 23:15 399 查看
KMP算法用于字符串的匹配。

1.KMP的原理

通常我们采用的方法是暴力匹配。时间复杂度为O(N*M)

这里面可能有很多冗余操作。

假设是在text字符串里面寻找pattern字符串。

假设N为text长度,M为pattern长度。

设N = 20, M = 8

我们从text和pattern的第一位开始比较,比较了5位,然后发现第6位不同。

如果是暴力解法,就会从text的第二位开始,然后又用pattern的第一位去开始匹配。

其实我们之前已经匹配了前5位了,也就是说text的前5位就是pattern的前5位,

我们现在在用pattern的第二位去匹配pattern的第一位。

但是pattern的第二位能不能匹配pattern的第一位,其实我们完全是知道的。

我们可以提前分析pattern,将pattern自身与自身有没有匹配的所有信息都记录下来。

放在一个叫做next的数组里面,然后要用到的时候随时查询。

之后我们每次匹配失败,我们就不用只移动一位了。

加入我们匹配了7位,然后第8位失败。

如果我们知道pattern的前7位,根本自身与自身没有重叠的,我们就直接移动7位,然后用pattern的第1位去和text的第9位比较即可。

如果我们知道pattern的前7位,有倒数2位和前2位是一样的,比如abcdeab,这个时候我们可以用pattern的第3位去和text的第9位比较。

2.算法的主线

根据1的描述。主要的流程就是这样的。

其中-1表示没有匹配,0表示有1位匹配,x表示有x+1位匹配

int kmp(char* text, char* pattern){

        int N = strlen(text), M = strlen(pattern);

int next* = (int*)malloc(sizeof(int) * M);

       compute_next(pattern, next);

for(int i = 0, j = -1; i < N; ++i){

while(i > -1 && text[i] != pattern[j + 1]){

j = next[j];

}

if(text[i] == pattern[i + 1]){

++j;

}

if(j == M - 1){

return i - M + 1;

}

}

}

解释,其中i是text的下标。

而j表示的是匹配的数量,-1表示没有匹配,0表示有1个匹配,所以当j == M - 1使表示M个匹配,就正好成功。

next数组表示的是pattern前x位对应有多少位是重叠的。

比如现在已经匹配了j位,next[j]就表示前j位有多少是重叠的,而现在的重叠就是移位后已经匹配的位数。

3.求取next数组
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: