1. 程式人生 > >hihoCoder 1015 KMP演算法(kmp)

hihoCoder 1015 KMP演算法(kmp)

小Hi和小Ho回到了學校,為了完成河蟹託付的偉大使命,小Hi立馬把小Ho抓到了機房開始上課。

“小Ho,你來看看這樣一段原串和模式串~”小Hi說著遞上了一張紙條。

原串: bababababababababb
模式串: bababb

“嗯,這個例子中模式串bababb在原串中第13個字元開始的地方出現了”小Ho看了看,回答道。

“我們假設仍然使用最普通的方法來進行判斷,即我們先列舉原串中的一個起始位置,然後判斷從這個位置開始的字串是否能和模式串進行完匹配。”小HI說道,“然後我們來看這個過程中有沒有什麼可以縮減的計算量。”

“好的!”小Ho點點頭。

“你看,在起始點為1的時候,匹配到第6個字元的時候發生了失敗,這個時候我們應當做的是是不是將模式串右移一位,然後從頭開始判斷,

就像這樣?”小Hi又在紙上畫了畫,遞給了小Ho。“

原串: bababababababababb
模式串: bababb
原串: bababababababababb
模式串: bababb

”是的,然後我們發現第一位就發現不能進行匹配。“小Ho老老實實的回答。

”然後我們再將模式串右移一位,然後再從頭開始判斷,這次我們成功的越過了原串的第7個字元,在第8個字元產生了不同。“小Hi繼續往下推演。

原串: bababababababababb
模式串: bababb

”然後之後的劇情非常的相似,都是要麼最後一個字元匹配不成功,要麼就是第一個字元就匹配不成功,一直到了最後一次機會的時候才匹配成功。“小Ho做了總結。

”那你覺得這個過程中有沒有什麼沒有必要計算的呢?“小Hi於是問道。

”我是這麼認為的,你看這條線。“小Ho在兩個串上對著的一個位置畫了一條線。

原串: babab | ababababababb
模式串: babab | b

”嗯?”

“這是我們第一次產生了字元不匹配的情況,那麼接下來的過程中一定會出現兩種情況之一:一種情況是模式串與原串的對齊點(即列舉的原串中的起點位置)越過了這條線,仍然沒能匹配成功,而另一種情況是原串中這個位置的字元與模式串中某個位置的字元匹配上了。”小Ho分析道:”我們先不考慮第一種情況,而來看看第二種情況會發生什麼。“

原串: babab | ababababababb
模式串(對齊點=1): babab | b
模式串(對齊點=3): bab | a

”看不出嘛,小Ho你今天變成聰明瞭嘛!~”小Hi由衷的讚歎道。

“那當然,畢竟我最近在討論區解答了很多問題,這很鍛鍊人的好麼!“小Ho笑嘻嘻的回答道。

”那我也得表現下,接下來換我來說吧,反正你肯定也就差不多想到這麼多是吧!“小Hi也是看破了小Ho的底細,這般說道。於是小Ho點了點頭,讓小Hi接著說。

”我相信一個很容易注意到的事實就在於,如果我用i表示原串和模式串產生分歧的位置(模式串上的位置,注意!這個和對齊點是不一樣的東西,一個在原串上,一個在模式串上),用j表示為了匹配掉位置i上產生分歧的字元而將模式串的對齊點移動到的位置,我們會發現,模式串[1, i-j]的這一段和[j, i - 1]這一段是相同的。比如在這個例子中i=6,j=3,我們會發現模式串[1, 3]和[3,5]是相同的。“小Hi整理了下思路,如是說道。

原串: ba | bab | a babababababb
模式串(i=1): ba | bab | b
模式串(i=3): | bab | a

”而我們同時也會發現,只有在存在一個長度k,使得模式串[1, i-k]和[k, i-1]這兩段相同的情況下,將模式串對其到位置k,才能保證原串和模式串的匹配過程能夠進入到原串的位置i是否和模式串的對應字元相同的判定,在別的情況下,根本都進入不到位置i的判斷就會發生不一致的情況了。”說著小Hi又丟擲了另外一個命題。

“我已經開始有點暈了!”小Ho提出了抗議。

“那你就好好的讀一遍我剛才說的話!然後自己在草稿紙上演算一下這個樣例,很快就可以得出結果的!”小Hi如是說道。”總而言之我們現在需要的一個數據是,這個長度k最長是多少,而且我們對於模式串的每一個位置i,都要計算這個值。”而這就是KMP中最為重要的一個點——NEXT陣列。