字串匹配-BF演算法和KMP演算法

gonghr發表於2021-03-13

宣告:圖片及內容基於https://www.bilibili.com/video/av95949609

BF演算法

原理分析

Brute Force 暴力演算法

用來在主串中查詢模式串是否存以及出現位置

 

 

核心就是回溯

如果模式串下標 j 始終沒有到達'\0'則沒有找到

如果主串下標 i 最後到達了'\0'則沒有找到

 

複雜度分析

 

完整程式碼

#include<iostream>
using namespace std;
int BF(char S[], char T[]) {
    int i = 0, j = 0,start=0;
    while (S[i]!='\0'&&T[j]!='\0') {
        if (S[i] == T[j]) {         //相等的話,i,j都後移一位
            i++; j++; 
        } 
        else {                        //一旦有不相等的,回溯。i回到起始位置加一,j回到模式串頭
            start++;
            i = i - j + 1;
            j = 0;
        }
    }
    if (T[j] == '\0') return start; //也可以return i-j;
    //if (S[i] == '\0') return -1;  //主串到達'\0'說明沒找到
    else return -1;                  //模式串沒到達'\0'說明沒找到
}
int main() {
    char S[] = "DABCDABD";
    char T[] = "ABD";
    int i=BF(S, T);
    if (i>=0) {
        cout << "已找到,在主串下標為"<<i<<"的地方"<<endl;
    }
    else cout << "未找到" << endl;
    return 0;
}

 KMP演算法

原理分析

比BF演算法高效,區別是主串的下標 i 不會回溯,一直前進。而模式串下標 j 回溯到特定位置。

關鍵是模式串找最大的相同的前字尾,用next陣列記錄前字尾字元數。

對模式串回溯的正確性分析:如上圖已經找到模式串中最大長度的相等的前字尾且模式串前字尾以及中間的元素已經與主串匹配。

模式串中ab!=cd,故模式串中ab!=主串中cd,模式串中的字首ab沒有再與主串比較的必要,故模式串下標 j 移動到c,主串下標 i 不動

next陣列

 

完整程式碼

#include<iostream>
using namespace std;
void getNext(char *T, int *next) {
    int j = -1;   //字首
    int i = 0;    //字尾
    next[0] = -1;
    while (i < strlen(T)) {
        if (j == -1 || T[i] == T[j] ){
            i++; j++;
            next[i] = j;
        }
        else {
            j=next[j];  //回溯
        }
    }
}
int KMP(char S[], char T[],int *next) {
    int i = 0, j = 0;
    int lengthS = strlen(S);
    int lengthT = strlen(T);
    while (i < lengthS && j < lengthT) {
        if (j== -1||S[i] == T[j]) {
            i++; j++;
        }
        else {
            j = next[j];
        }
    }
    if (j == lengthT) return (i - j);
    else return -1;
}

int main() {
    char S[] = "DABCDABD";
    char T[] = "ABC";
    int next[100];
    getNext(T,next);
    int i = KMP(S, T,next);
    if (i>=0) {
        cout << "已找到,在母串下標為"<<i<<"的地方"<<endl;
    }
    else cout << "未找到" << endl;

    return 0;
}

 

BF演算法和KMP演算法比較

在KMP演算法中 j == -1因為next陣列next[0]= -1,得到 j 可能為-1

相關文章