模式串匹配KMP详解

关于KMP模式串匹配网上蛮多的.

对于KMP有自己理解所以写下来希望能够对你们的学习有帮助.

之前暑假的时候学过,然后好长时间没用发现又忘了,现在再看看发现有了新的理解.

======================================================================

1.关于KMP的next数组的问题.

相信很多童鞋会迷在这里,next到底是干什么的?

next保存的是第i个位置前缀串和后缀串第一个字符不相同的位置.

下面我们来画图理解一下

next[11] = 4

next[11]也就是k的位置,下面我们来解释一下为什么K的next为什么是4

首先是前缀串和后缀串, 我们是以K前面的位置开始,来进行匹配,可以看我们串的红色部分,就分别是我们的前缀串(从字符串开头到C的前一个位置为前缀串)和后缀串.

K的next就是最先不匹配的位置.也就是C了, C的下标就是4.

2.知道了next然后我们如何去匹配呢??

上我们的第二张图

.

解释一下:

第一次串匹配,当我们匹配到i的位置的时候,我们会判断i和主串的相应位置是否匹配.如果匹配继续向下匹配,如果不匹配则按照下面的规则进行.

在不匹配的情况下:按照传统的模式串匹配我们要从第一个串的位置开始要重新进行匹配.

但是现在我们并不需要从第一个位置开始了.要从什么位置开始呢?从我们的next[i]的位置重新开始匹配就行了.

第二次串匹配:第二次串匹配就是从next[i]的位置重新开始匹配. 因为我们知道前缀串和后缀串是一样的,因此我们的重新匹配的位置就不需要大的改动了.

=================================================================================

下面就是代码的实现:   

 

#include<stdio.h>
#include<string.h>
#define maxn 1000

void GetNext(int next[],char T[])
{
    int len = strlen(T), i = 0, j = -1;
    next[0] = -1;

    while(i < len)
    {
        if(j == -1 || T[i] == T[j])//说明 next[i]要更新
        {
            i ++;
            j ++;
            next[i] = j;
        }
        else
            j = next[j];
    }
}

int KMP(char S[],char T[])
{
    int next[maxn], i = 0, j = 0;
    int lenS = strlen(S);
    int lenT = strlen(T);
    GetNext(next, T);

    while(i < lenS && j < lenT)
    {
        if(j == -1 || S[i] == T[j] )
        {
            i ++;
            j ++;
        }
        else
        {
            j = next[j];
        }
    }

    if(j == lenT)
        return i-j;
    return -1;
}

int main()
{
    char S[maxn], T[maxn];

    scanf("%s %s",S, T);

    int ans = KMP(S,T);

    printf("%d\n", ans);

    return 0;
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

posted @ 2016-04-20 14:16  向前走丶不回首  阅读(408)  评论(0编辑  收藏  举报