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海子大神的,不過有些定義是修改了一下

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章