【C】KMP算法手工實現

前提

本文采用下標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算法的時間複雜度是O(m+n)O(m+n),而BF算法的時間複雜度爲O(mn)O(mn),但是實際上BF算法在計算機執行時間近似於O(m+n)O(m+n),所以BF算法仍然廣泛使用,KMP算法比較適合主串和模式串有很多“部分匹配”的情況。

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