[英]string matching with finite automata
我正在閱讀Cormen的書“算法導論”中的字符串算法。 對於過渡,如下所示。
我的問題:為什么我們要做min(m+1, q+2)
,為什么我們要m遞增1,q遞增2。
以下鏈接有上述問題。
http://people.scs.carleton.ca/~maheshwa/courses/5703COMP/Fall2009/StringMatching.pdf
請幫助一個簡單的例子。
Algorithm Compute-Transition-Function(P, Sigma)
m = length(P);
for q = 0 through m do
for each character x in Sigma
k = min(m+1, q+2);
repeat k = k-1 // work backwards from q+1
until Pk 'is-suffix-of' Pqx;
d(q, x) = k; // assign transition table
end for;
end for;
return d;
End algorithm.
m + 1
因為在下一個repeat
循環中, k
首先減小。 q + 2
因為在repeat
你開始然后用q + 1
所以至少有1個字符。
以下代碼可能存在邊界問題(q == m丟失),但希望使索引更清晰。
m = length(P);
for q = 0 through m - 1 do // Loop through substrings [0, q+1]
for each character x in Sigma
k = q+1;
// work backwards from q+1
while not Pk 'is-suffix-of' Pqx;
do k = k-1; end do;
d(q, x) = k; // assign transition table
end for;
end for;
return d;
代碼已被解釋,所以這里是一個例子來看看發生了什么
假設字符串是nano
所以我們希望我們的狀態與模式部分匹配。 與"nano"
部分匹配可能是"", "n", "na", "nan", or (the complete match) "nano"
本身。 換句話說,它們只是字符串的前綴。 一般來說,如果模式有m個字符,我們需要m + 1個狀態; 這里m = 4,有五個州。
如果我們剛看到"...nan"
,看到另一個字符"x"
,我們應該去哪個州? 顯然,如果x是匹配中的下一個字符(這里是“o”),我們應該轉到下一個更長的前綴(這里是“nano”)。 很明顯,一旦我們看到完全匹配,我們就會保持這種狀態。 但是假設我們看到一個不同的角色,比如"a"
? 這意味着到目前為止,字符串看起來像"...nana"
。 我們可能會遇到的最長的部分匹配只是"na"
,即我們可以利用最后2個字符。 因此,從狀態"nan"
,我們應繪制一個標記為"a"
的箭頭,將狀態為"na"
。 請注意, "na"
是"nano"
(因此是狀態)的前綴,並且是"nana"
的后綴(因此是與我們剛剛看到的部分匹配的部分)。
通常,從狀態+字符到狀態的過渡是最長的字符串,它同時是原始模式的前綴和我們剛剛看到的狀態+字符的后綴。 這足以告訴我們所有轉換應該是什么。 如果我們正在尋找模式"nano"
,那么過渡表就是
n a o other
--- --- --- ---
empty: "n" empty empty empty
"n": "n" "na" empty empty
"na": "nan" empty empty empty
"nan": "n" "na" "nano" empty //just as an illustration, nan + n = n because we can only use the last 'n', nan + a = na because now we can use the last two 'na'
"nano": "nano" "nano" "nano" "nano"
那么現在我們如何使用這個表來實際進行模式搜索?
在字符串"banananona"
上模擬這個,我們得到狀態序列為空,空, "n", "na", "nan", "na", "nan", "nano", "nano", "nano"
通過一次移動一個角色。 由於我們以狀態"nano"
結束,因此該字符串在某處包含"nano"
。 所以讓我們來看看最新情況以及如何使用上面的表格,在'b',我們沒有任何可能的狀態'n', 'na', 'nan', 'nano'
。 所以它算得空了......就像我們到了'ba'
。 當我們打到下一個字符'n'
,基本上是從空到n,因此我們使用上面的表,並看到它以'n'
結尾。 現在我們得到了banananona的4個角色,所以我們從'n'
開始添加...再次我們使用該表並看到它最終處於'na'
狀態,依此類推......
轉換表中的條目d(q,x)
包含消耗字符x
后模式的最長匹配前綴的長度,如果在消耗x
之前,最長匹配前綴是q
字符長。 因為我們消耗一個字母,所以它不能大於q+1
,並且由於該模式具有長度m
,所以它也可以最多為m
。 內循環repeat k = k-1 until condition(k)
,因此在測試任何東西之前, k
都會遞減,因此k
必須以大於最大可能結果的1開始, k = min(m,q+1) + 1
。 如果內部循環是while negated_condition(k) { k = k-1; }
while negated_condition(k) { k = k-1; }
,將從k = min(m,q+1)
。
注意,通過將邊界表用於Knuth-Morris-Pratt算法,可以更高效地計算轉換表。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.