給定字串m和n(m比n長),找出n在m中出現的匹配位置。說白了,就是乙個簡單的字串匹配。
例如:
首先,字串」bbc abcdab abcdabcdabde」的第乙個字元與搜尋詞」abcdabd」的第乙個字元進行比較。因為b與a不匹配,所以搜尋詞後移一位。
因為b與a不匹配,搜尋詞再往後移。
就這樣,直到字串有乙個字元,與搜尋詞的第乙個字元相同為止。
接著比較字串和搜尋詞的下乙個字元,還是相同。
直到字串有乙個字元,與搜尋詞對應的字元不相同為止。
這時,最自然的反應是,將搜尋詞整個後移一位,再從頭逐個比較。這樣做雖然可行,但是效率很差,因為你要把」搜尋位置」移到已經比較過的位置,重比一遍。
移動位數 = 已匹配的字元數 - 對應的部分匹配值因為 6 - 2 等於4,所以將搜尋詞向後移動4位。即:
因為空格與a不匹配,繼續後移一位。
逐位比較,直到發現c與d不匹配。於是,這次的移動位數 = 6 - 2 = 4,繼續將搜尋詞向後移動4位。
從這個過程可以發現,計算部分匹配表是關鍵。
首先,要了解兩個概念:」字首」和」字尾」。 「字首」指除了最後乙個字元以外,乙個字串的全部頭部組合;」字尾」指除了第乙個字元以外,乙個字串的全部尾部組合。
「部分匹配值」就是」字首」和」字尾」的最長公共子串的長度。以」abcdabd」為例,
「部分匹配」的實質是:有時候,字串頭部和尾部會有重複。比如對於」abcdab」之中有兩個」ab」,那麼它的」部分匹配值」就是2(」ab」的長度)。搜尋詞移動的時候,第乙個」ab」向後移動4位(字串長度-部分匹配值),就可以來到第二個」ab」的位置。
建立部分匹配表的核心內容就是根據待匹配的模板字串求出對應每一位的最大相同前字尾的長度。
void makenext(string p,vector
&next)
}
while迴圈所做的工作:
已知前一步計算時,位置(q-1)處的字元的最大匹配前字尾長度為k(k>0),即str[0]···str[k-1]和str[q-k]···str[q-1]相匹配。
此時比較q處的字元的匹配長度。如果字首的str[k]等於字尾的str[q],那麼很簡單跳出while迴圈;
如果不等呢?那麼我們應該利用已經得到的next[0]···next[k-1]
來求str[0]···str[k-1]
的最大相同前字尾。
為什麼要求str[0]···str[k-1]
的最大相同前字尾呢?原因在於str[k]已經和str[q]失配了,而且str[q-k] ··· str[q-1]
又與str[0] ···str[k-1]
相同,這麼一來,str[0]···str[k-1]是不可能作為部分匹配前字尾子串了,那麼下面我就要找str[0]···str[k-1]的部分匹配前字尾子串str[0]···str[j-1](j==next[k-1])
,看看它的下一項str[j]是否能和str[q]匹配。
}鏈
字串 KMP演算法
而kmp演算法在字串匹配方法中乙個很著名並且很聰明的演算法,當然也確實比較難理解。甚至於有程式設計師因為無法理解kmp演算法而直接改用暴力匹配。本身自己學演算法起步較晚,第一次接觸到kmp演算法已經是研究生畢業一年了。雖然帶著研究生的學歷背景,但是剛開始看的時候依然是一臉懵逼。看了很多博主的講解總算...
字串 KMP演算法
而kmp演算法在字串匹配方法中乙個很著名並且很聰明的演算法,當然也確實比較難理解。甚至於有程式設計師因為無法理解kmp演算法而直接改用暴力匹配。本身自己學演算法起步較晚,第一次接觸到kmp演算法已經是研究生畢業一年了。雖然帶著研究生的學歷背景,但是剛開始看的時候依然是一臉懵逼。看了很多博主的講解總算...
字串匹配演算法 KMP演算法
kmp演算法是一種改進的字串匹配演算法。kmp演算法的關鍵是利用匹配失敗後的資訊,儘量減少模式串與主串的匹配次數以達到快速匹配的目的。具體實現就是實現乙個next 函式,函式本身包含了模式串的區域性匹配資訊。下面從乙個例子來了解kmp演算法 字串 bbc abcdab abcdabcdabde 我想...