宣告:圖片及內容基於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