kmp演算法的核心思想:設法讓主串不回退,讓子串回退的更少整個過程分為兩步:
為子串建立一張最長匹配長度的表
利用這種表的索引對主串實現匹配判斷
測試樣本:規則:對每個子字串 [0…i],算出其「相匹配的字首與字尾中,最長的字串的長度」。例如:主串:"fsaabababzabababaaba"
子串:"abababzabababa"
當i=5時,對子字串ababab來說
字首:a、ab、aba、abab、ababa
字尾:b、ab、bab、abab、babab
此時最長匹配長度為4,匹配項為abab,同時其中同時看到另外乙個匹配項ab
了解了這張表的來歷,那麼應該怎樣簡化運算來求解最後一位a的最長匹配長度呢?
當i=12時,對子字串 abababzababab 來說,
字首:a, ab, aba, abab, ababa, ababab, abababz, ...
字尾:b, ab, bab, abab, babab, ababab, zababab, ...
子字串abababzababab
字首字尾最大匹配了6個(ababab),那次大匹配了多少呢?容易看出次大匹配了4個(abab),更仔細地觀察可以發現,次大匹配的字首字尾只可能在 ababab 中,所以次大匹配數就是 ababab 的最大匹配數!第三大同理,可得abab
的最大匹配數,查表可得該值為2。
?處找最大匹配發現結尾不是z,所以就不能直接6+1=7,應該找次大匹配,發現剛好對上abab後的字元a,所以?為4+1=5,匹配項為abab
到此為止,第一步已經完成了
**如下:
// 構造 pattern 的最大匹配數表
public
static
int[
]calculatemaxmatchlengths
(string pattern)
if(pattern.
charat
(i)== pattern.
charat
(maxlength)
) maxmatchlengths[i]
= maxlength;
}return maxmatchlengths;
}
既然子串的表已經建立,那麼下一步就是對主串使用了
首先,主串是不回退的,所以這裡用for迴圈實現從頭到尾的遍歷,同時對應尋找子串的最大匹配
在迴圈內部分三種情況執行:
部分匹配成功,指標i和count往後移動
匹配失敗,改變count,尋找次大匹配
完全匹配成功,記錄位置
public
static list
kmp_search
(string text,string pattern)
if(pattern.
charat
(count)
== text.
charat
(i))
if(count == pattern.
length()
)}return positions;
}
好了,到此為止kmp演算法的核心已經寫完了,下面開始測試:
理解KMP演算法
由暴力匹配引入kmp演算法 問題 有乙個文字串s,和乙個模式串p,現在要查詢p在s中的位置。如果用暴力匹配的思路,並假設現在文字串s匹配到 i 位置,模式串p匹配到 j 位置,則有 示例 上面s,下面p 比如從a這裡開始匹配上了 一直這樣匹配下去 到這裡匹配不上了 就回滾回去重新開始 這種回滾的問題...
理解KMP演算法(引用)
理解kmp演算法 引用 通用性的kmp演算法 void getnext st t,int next 由子串t求出next值 else k next k 滑動過程中如果出現不相等則認為以k個字元相等進行下一次滑動 kmpindex st s,st t,int pos maxstrlen為一常量,用來定...
KMP 演算法(個人理解)
相信大家看了 matrix67 的講解,一定已經知道了 kmp 演算法是怎麼回事,怎麼操作的,為什麼時間複雜度不高 這裡,我主要是分享我對 kmp 的理解 kmp 的精髓是什麼?這個東西,各自有個字的理解,很多人都覺得是避免了重複匹配,而我的理解是預處理 為什麼是預處理?你看看 kmp 的執行過程 ...