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