前提
本文采用下標0開始的數組來實現next數組,下標1開始的代碼以註釋表示。
主串:ababcabcacbab
模式串:abcac
計算所得next數組:-1 0 0 0 1
next數組代碼:
void get_next(int next[],char str[]){
next[0]=-1;//next[1]=0
int i,j;
i=0,j=-1;//i=1,j=2;
while(i<strlen(str)){
if(j==-1||str[i]==str[j]){//(j==0||str[i]==str[j])
next[++i]=++j;
}else{
j=next[j];
}
}
}
查找模式串位置模板
int findPos(char a[],char b[],int pos,int next[]){
//查找子串b在主串a中起始下標,pos爲查找起始位
int i,j;
i=pos,j=0;
while(i<strlen(a)&&j<strlen(b)){
if(j==0||a[i]==b[j]) i++,j++;
else j=next[j];
}
if(j<lenB) return -1;//查找失敗返回-1
else return i-strlen(b);
}
代碼
#include <stdio.h>
#include <string.h>
#define maxsize 100//數組最大長度
char strA[]="ababcabcacbab";//主串
char strB[]="abcac";//模式串
int lenA,lenB;//串長
int kmp[maxsize];//next數組
void get_next(int next[],char str[]){//求next數組
next[0]=-1;//next[1]=0
int i,j;
i=0,j=-1;//i=1,j=2;
while(i<strlen(str)){
if(j==-1||str[i]==str[j]){//(j==0||str[i]==str[j])
next[++i]=++j;
}else{
j=next[j];
}
}
}
int findPos(char a[],char b[],int pos,int next[]){
//查找子串b在主串a中起始下標,pos爲查找起始位
int i,j;
i=pos,j=0;
while(i<lenA&&j<lenB){
if(j==0||a[i]==b[j]) i++,j++;
else j=next[j];
}
if(j<lenB) return -1;//查找失敗返回-1
else return i-lenB;
}
int main(){
int i,j;
lenA=strlen(strA);
lenB=strlen(strB);
get_next(kmp,strB);
printf("mainString:%s\nSubString:%s\nnextList:",strA,strB);//輸出兩個串
for(i=0;i<lenB;i++){
printf("%d ",kmp[i]);//輸出next數組
}
printf("\nSubList's Position:%d",findPos(strA,strB,0,kmp));//輸出下標
return 0;
}
輸出數據
mainString:ababcabcacbab
SubString:abcac
nextList:-1 0 0 0 1
SubList's Position:5
後記
設主串和模式串長度分別爲m,n
KMP算法的時間複雜度是,而BF算法的時間複雜度爲,但是實際上BF算法在計算機執行時間近似於,所以BF算法仍然廣泛使用,KMP算法比較適合主串和模式串有很多“部分匹配”的情況。