KMP(1)--KMP算法解析

KMP(1)--KMP算法解析

1. 普通字符串匹配BF算法

假设S串为原始串, T串为目标串S串匹配到i位置, T串匹配到j位置.

BF算法中如果当前字符匹配成功, (S[i+j] == T[j]) j++, 继续匹配下一个字符如果失配, (S[i+j] != T[j]), 需要i++, j = 0; 也就是目标串相对于原始串向右移动了一位.

代码如下 

    int index(char* s, char* t){

        int slen = strlen(s);

        int tlen = strlen(t);

        if (slen < tlen || slen <= 0 || tlen <= 0){

            return -1;

        }

        int i = 0;  ///< record position in s string

        int j = 0;  ///< record position in t string

        while (i <= slen && j <= tlen){

            if (s[i + j] == t[j]){

                ++j;

            }

            else{

                j = 0;

                ++i;

            }

        }

        if (j == tlen){

            return i;

        }

        return -1;

    }

对于普通的匹配算法来说回溯是无法避免的因为它必须对S串中的每个位置的i, 相对于T串中的j进行检测是否匹配在每次检测的失配情况下, i的位置才会发生变化.

2. 使用KMP算法如何避免回溯

先看看下面的例子 第一行是S第二行是T

a

c

a

c

d

......

a

c

a

c

b

--->

a

c

a

c

b

S串和T串在匹配到第五个字符时失配那么如果这时T串能够右移2那么就可以继续下面的匹配如第三行所示同样的道理如果当T串当前的匹配位置j失配了那么j可以向右移动的值即为jnext.

3. next数组的含义

这一部分解释什么是next数组.

另原始串S[i], 0<=i<=n; 模式串T[i], 0<=i<=m

假设当前的匹配情况如下 

S0

S1

S2

...

Si-j

Si-j+1

Si-j+2

...

Si-2

Si-1

Si

Si+1

Si+2

...

Sn

T0

T1

T2

...

Tj-2

Tj-1

Tj

...

T0

T1

...

Tj-3

Tj-2

Tj-1

...

如果S[i-j, i-1] == T[0, j-1]并且T[1, j-1] == T[0, j-2], (上图中蓝色的部分为匹配的情况)那么我们可以当SiTj失配的情况下j = j-1, 让匹配的过程继续下去这时, i没有发生改变, j的位置向左移动了一位也就是说, T相对于S向右移动了一位.

PS : 下面是重点哦....

也就是说SiTj时失配的情况下如果要达到i不变, T串相对于S串右移的目的可以更新j的值T串和S串继续匹配.

假设新的j值用next[j]表示如果能够保证 :

T[j-1-next[j], j-1] == T[0, next[j]]

那么就可以让SiTnext[j]继续进行匹配的过程当然前提条件是next[j]<=j-1next[j]即为T[0, j-1]前部分和后部分相等的长度也就是说next值于T串本身相关而于S串无关. next数组即为KMP算法的精髓所在.


posted on 2012-01-07 14:35 Apollo Fang 阅读(257) 评论(0)  编辑 收藏 引用 所属分类: Algorithm


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


导航

随笔分类

随笔档案

最新评论