講kmp演算法,離不開bf,實際上,kmp就是bf公升級版,主要流程和bf一樣
不同是在匹配失敗時能利用子串的特徵減少回溯,利用根據子串特徵生成的next陣列來減少
!!!所有陣列下標都是從0開始
int brute_force_1(const char *s, const char *t)
} if (j == lent)
return i - j;
return -1;
}
bf演算法有幾種不同實現,但最終思想都是一樣的,以下就是另乙個bf實現
int brute_force_2(const char *s, const char *t)
if (j == lent)
return i; //說明匹配到了
} return -1;
}
你完全可以根據自己的理解寫出bf演算法,但在這裡,為了bf和kmp統一,我們還是採用第一種實現,即容易看出回溯操作的實現
事實上,書上的next陣列生成演算法是經過優化後的演算法,比較難懂,但你完全可以按照自己的理解做乙個
注意:next陣列只是在kmp中字串匹配失敗時使用的
void getnext(int next, char *str)
else next[i]=0;
} }}
這個時間複雜度要比書上的方法高很多,但好理解,真實的反映了next陣列的本質。
int kmp(const char *s, const char *t, const int *next)
else j = next[j];//主串i位置不變,講子串下標索引挪到next[j]的位置
} }if (j == lent)
return i - j;
return -1;
}
這個回溯時的操作實際上是把兩種情況合成一種,拆開後就是下面的,就是生成next陣列那塊三種情況
while (i < lens && j < lent)
else if (next[j] == 0)
else}}
next陣列有進一步改進的可能,如果發生失配,失配點子串字元若與回溯到的字元相同,則再次匹配肯定失敗,所以改進的next陣列進一步處理了這種情況,消除了回溯
void getnext_pro(int next, const char *str)
else next[i]=0;
} }}
測試**
int kmp(const char *s, const char *t)
; getnext(next,t);
print_arr(next, strlen(t));
getnext_pro(next,t);
print_arr(next, strlen(t));
int lens = strlen(s);
int lent = strlen(t);
int i = 0; //主串下標索引
int j = 0; //子串下標索引
while(i < lens && j < lent)
else j = next[j];//主串i位置不變,將子串下標索引挪到next[j]的位置
} }if (j == lent)
return i - j;
return -1;
}int main(void)
附上bf與kmp的比較,你會發現兩者其實挺相似
其實核心就在於本文第一句話的理解。
kmp在子串含有相同前字尾時,利用next陣列減少匹配失敗時的回溯次數有優勢,而改進的next陣列在此基礎上若子串含有較多相同字元則更進一步減少回溯。
所以kmp總之是利用子串的特徵來削除回溯,如果子串並不具有這些特徵,那就還沒有bf好,因為kmp還需要額外的空間來存放next陣列
書上的next陣列的生成很難懂,加油理解中。。。(ง •_•)ง
KMP演算法解釋
有些演算法,適合從它產生的動機,如何設計與解決問題這樣正向地去介紹。但kmp演算法真的不適合這樣去學。最好的辦法是先搞清楚它所用的資料結構是什麼,再搞清楚怎麼用,最後為什麼的問題就會有恍然大悟的感覺。我試著從這個思路再介紹一下。大家只需要記住一點,pmt是什麼東西。然後自己臨時推這個演算法也是能推出...
演算法 KMP演算法 解釋
1.詳解kmp演算法 2.大話資料結構 3,kmp演算法易懂版 kmp演算法由d.e.knuth j.h.morris和v.r.pratt發表的模式匹配演算法。kmp演算法要解決的問題就是在字串 也叫主串 中的模式 pattern 定位問題。例子 輸入 主串 s abeabx 子串 t abx 輸出...
字串匹配演算法 KMP演算法簡單解釋
kmp演算法是一種改進的字串匹配演算法,由d.e.knuth,j.h.morris和v.r.pratt同時發現,因此人們稱它為克努特 莫里斯 普拉特操作 簡稱kmp演算法 kmp演算法的關鍵是利用匹配失敗後的資訊,儘量減少模式串與主串的匹配次數以達到快速匹配的目的。具體實現就是實現乙個next 函式...