模式匹配是數據結構中字符串的一種基本運算,給定一個子串,要求在某個字符串中找出與該子串相同的全部子串,這就是模式匹配。html
文中代碼是本人本身寫的,實測有效,含JAVA和C++兩種代碼。乾貨充足吧。
ios
蠻力算法(Brute-Force),簡稱BF算法。(男友算法,簡單粗暴—_—!)程序員
算法思想算法
BF算法的算法思想是: 數組
從目標串T的的第一個字符起與模式串P的第一個字符比較。數據結構
若相等,則繼續對字符進行後續的比較;不然目標串從第二個字符起與模式串的第一個字符從新比較。ide
直至模式串中的每一個字符依次和目標串中的一個連續的字符序列相等爲止,此時稱爲匹配成功,不然匹配失敗。性能
經過下圖示例,可一目瞭然: spa
算法性能指針
假設模式串的長度是m,目標串的長度是n。
最壞的狀況是每遍比較都在最後出現不等,即沒變最多比較m次,最多比較n-m+1遍。
總的比較次數最多爲m(n-m+1),所以BF算法的時間複雜度爲O(mn)。
BF算法中存在回溯,這影響到效率,於是在實際應用中不多采用。
代碼
JAVA版本
C++版本
運行結果
Knuth-Morris-Pratt算法(簡稱KMP),是由D.E.Knuth、J.H.Morris和V.R.Pratt共同提出的一個改進算法,消除了BF算法中回溯問題,完成串的模式匹配。
算法思想
顯然,移回到前面已經比較過的位置,仍是不能徹底匹配。
KMP算法的思想是,設法利用這個已知信息,跳過前面已經比較過的位置,繼續把它向後移,這樣就提升了效率。
由此可知,KMP算法其實有兩大要點:
(1) 計算跳轉位置信息,這裏咱們稱之爲部分匹配表。
(2) 後移到指定位置,從新開始匹配。
首先,來看如何得到部分匹配表。
這個next 數組叫作部分匹配表。
對於next[]數組的定義以下:
對於BF算法中的例子,模式串P=「abcac」,根劇next[j]的定義,可獲得下表:
j | 0 | 1 | 2 | 3 | 4 |
t[j] | a | b | c | a | c |
next[j] | -1 | 0 | 0 | 0 | 1 |
有了部分匹配表,就能夠後移到指定位置
若是next[j] >= 0,則目標串的指針 i 不變,將模式串的指針 j 移動到 next[j] 的位置繼續進行匹配;
若next[j] = -1,則將 i 右移1位,並將 j 置0,繼續進行比較。
以上要點配合下面的示意圖理解,效果會更好哦。
算法性能
在KMP算法中求next數組的時間複雜度爲O(m),在後面的匹配中因目標串T的下標不用回溯,因此比較次數可記爲n。
由此,得出KMP算法的總的時間複雜度爲O(n+m)。
代碼
JAVA版本
運行結果
http://www.ruanyifeng.com/blog/2013/05/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm.html
http://www.cnblogs.com/dolphin0520/archive/2011/08/24/2151846.html
歡迎閱讀 程序員的內功——算法 系列