KMP算法

KMP算法


在KMP算法中,为了确定在匹配不成功时,下次匹配时j的位置,引入了next[]数组,next[j]的值表示T[1...j-1]中最长后缀的长度等于相同字符序列的前缀。

数据结构的算法书上的定义,这里假设模式串中的T[0],以及主串中的S[0]都是用来存储字符长度的。

对于next[]数组的定义如下:

1)next[j]=0  j=1

2)next[j]=max k: 1<k<j  T[1...k-1]=T[j-k+1,j-1]

3)next[j]=1  其他情况


即next[j]=k>1时,表示T[1...k-1]=T[j-k+1,j-1]

因此KMP算法的思想就是:在匹配过程称,若发生不匹配的情况,如果next[j]>0,则目标串的指针i不变,将模式串的指针j移动到next[j]的位置继续进行匹配;若next[j]=0,则将i右移1位,并将j置1,继续进行比较。


#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#define TRUE  1
#define FALSE  0
#define OK  1
#define ERROR  0
#define INFEASLBLE  -1
#define OVERFLOW  -2
#define MAXSTRLEN  255 	//用户可在255以内定义最大串长
typedef  char SString[MAXSTRLEN+1];	//0号单元存放串的长度

void get_next(SString T,int next[]){
// 算法4.7
// 求模式串T的next函数值并存入数组next

/*
  KMP算法的关键在于求算next[]数组的值,即求算模式串每个位置处的最长后缀与前缀相同的长度, 而求算next[]数组的值有两种思路,第一种思路是用递推的思想去求算,还有一种就是直接去求解。

   1.按照递推的思想:

   根据定义next[1]=0,假设next[j]=k, 即T[1...k-1]==T[j-k+1,j-1]

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

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

*/
   int k=0,j=1;
   next[1]=0;//根据数据结构书上的定义第一个应为0
   while(T[j]!='\0')
   {
       if(k==0||T[j]==T[k])
       {
           k++;
           j++;
           next[j]=k;
       }
       else
       {
           k=next[k];
       }
   }


return ;
}

int Index_KMP(SString S,SString T,int pos){
// 算法4.6
// 利用模式串T的next函数求T在主串S中第pos个字符之后的位置

    int j=1,i=1;
    int next[1000+10];

    get_next(T,next);//计算next值

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

        if(j>T[0])//T串已经比较完毕,确定是主串的子串
        {
            return i-T[0];
        }
    }

  return 0;//否则返回值为0
}

    int main()
    {
        SString T,S;
        int i,j,n;
        char ch;
        int pos;
        scanf("%d",&n);    // 指定n对需进行模式匹配的字符串
        ch=getchar();
        for(j=1;j<=n;j++)
        {
        ch=getchar();
        for( i=1;i<=MAXSTRLEN&&(ch!='\n');i++)    // 录入主串
        {
            S[i]=ch;
            ch=getchar();
        }
        S[0]=i-1;    // S[0]用于存储主串中字符个数
        ch=getchar();
        for( i=1;i<=MAXSTRLEN&&(ch!='\n');i++)    // 录入模式串
        {
            T[i]=ch;
            ch=getchar();
        }
        T[0]=i-1;    // T[0]用于存储模式串中字符个数
        pos= Index_KMP(S,T,0);   //答案pos
        printf("%d\n",pos);
        }
        return 0;
    }
本文某些解释参考http://www.cnblogs.com/dolphin0520/archive/2011/08/24/2151846.html海子大神的,不过有些定义是修改了一下

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值