KMP算法学习

来源:互联网 发布:手机淘宝开店我是卖家 编辑:程序博客网 时间:2024/06/03 20:07

1.   KMP算法简介

    KMP算法,是由Knuth,Morris,Pratt共同提出的模式匹配算法,其对于任何模式和目标序列,都可以在线性时间内完成匹配查找,而不会发生退化,是一个非常优秀的模式匹配算法。

2.   朴素的匹配算法

在介绍KMP算法之前我们来看看那朴素的匹配算法。定义:我们是在主串中搜索模式串。如下图当主串在e的位置与模式串发生失配时(e前面的都是匹配的),朴素的匹配算法做的是,将模式串后移一位在去匹。我们可以思考这样做是否有意义,因为模式串c前面是与主串匹配的,我们将模式串向后移动一位,与其自身对比,显然是无法匹中的,那么与主串肯定也是无法匹配的。那么应该移动多少位合适呢,这就是KMP算法讨论的问题。

3.   Kmp算法详解

KMP算法主要为每个字符建立一个跳转表,通常用next数组来表示。next[j]=k的含义是,当主串中第i个元素与模式串中的第j个元素不匹配时,,我们应当保持i指针不动,而将模式串中的下标为k的元素与主串中的下标为i的元素对齐。

简单的解释是:当模式串中第j个元素与主串匹不中时,应该跳转到第k个元素与主串去匹配。

Next数组的构造是kmp算法的核心。

KMP next数组的构造:

   根据定义next[0]=-1,假设next[j]=k, 即P[0...k-1]==P[j-k,j-1](1)

   1)若P[j]==P[k],则有P[0..k]==P[j-k+1,j],很显然,next[j+1]=next[j]+1=k+1;

   2)若P[j]!=P[k],则可以把其看做模式匹配的问题,即匹配失败的时候,k值如何移动,显然k=next[k]。

1)        显然,关键是2),2)的证明如下:

因为 next[j]=k

则:p[0….k-1] =p[j-k…..j-1]

     又P[j]!=P[k]

则下面的任务是要找

P[0..k’]  是否有等于  p[j-k’..j]的    k’<k

因为  p[j-k’…j-1]= p[ k-k’…k-1]

因此只要检查是否存在k’使得    p[0..k’-1]= p[ k-k’…k-1] (2)并且p[k’]=p[j]

若存在则,next[j]=k’

比较(1)  (2)两式可得   k’=next[k]

即:next[j]=next[next[j-1]

若p[k’]=p[j]还不相等,接着迭代

 

4.kmp算法测试程序 

#include<stdio.h>

#include<string.h>

#include<stdlib.h>

 

voidmakenext(const char c[],int *next)

{

      int i=0,k=-1;

      next[0]=-1;

      int ilen = strlen(c);

      while(i<ilen)

      {

           while(k>=0&&c[i]!=c[k])

                 k = next[k];

           i++;k++;

           next[i] = k;

      }

}

 

intKMPsearch(const char *pstrObj,const char *pstrPattern)

{

        int iobjlen,ipatternlen;

        iobjlen = strlen(pstrObj);

        ipatternlen = strlen(pstrPattern);

        int next[iobjlen];

        makenext(pstrPattern,next);

        int i=0,j=0;

       while(j<ipatternlen&&i<iobjlen)

        {

                if(j==-1||pstrPattern[j] ==pstrObj[i])

                {

                        i++;

                        j++;

                }

                else

                {

                        j=next[j];

                }

        }

 

      if(j==ipatternlen)

      {

           return (i-ipatternlen);

      }

      else

      {

           return -1;

      }

}

int main()

{

      char str[20]="cfababacfgf";

      char pattern[10] = "ababac";

      int iStart;

      iStart = KMPsearch(str,pattern);

      if(iStart == -1)

      {

           printf("NOT FOUND!\n");

      }

      else

      {

           printf("finded, Obj stringPos:%d\n",iStart);

      }

}

0 0
原创粉丝点击