kmp算法

 kmp算法剛開始看時都唔覺得那麼難,大概是因爲我以自己真正懂了,真是天真的小夥子。後來越看就越發現一切都不是那麼簡單

首先這是一個字符串匹配問題,現要在主串S中找子串T,對於普通的算法,相信沒有人會不會的說。我這不是在教人(這一定要聲明,那位大蝦行過路過,還望指點一二)

只不過是想看完寫下來,方便以後自己有用,畢竟自己寫的東西自己看是容易理解很多的說

       入正題,現在假設我們在匹配過程中,當到匹配到主串S的第i個字符與子串的第j個字符時出現所謂的“失配”,也就是S[i]!=[T[i],

並且有T的前j-1個字符“T[0]……T[j-1]" ==”S[i-j]……S[i-1]",此時必須去向右移動T串去尋找另外的匹配,在正常情況下(也就是最笨的方法)一般會反T串右移一位

然後回溯i,使得s[i-j+1]與T[1]比較,此時作向右移動一步的決定是因爲我們總是認爲只有向右移一步就可以找到匹配,假設我們真的移動一步就找到,也就是說當我們

找到匹配時那一定有“T[0]……T[j-2]" = "S[i-j+1]……S[i-1]",結全前式就有”T[0]……T[j-2]“ = ”T[j-1-(j-2)](T[2])……T[j-1]“(有點亂的,見諒,見諒),但大部份情況系

沒有這種RP,移動一步後並不能得到匹配,沒辦法了,只能繼續向右移動一步啦,我們總期待着下一步就是匹配,所以移動後我們又開始不厭其煩的開始匹配每一個T

中的字符是否與移動後對應的S串中的字符匹配,這樣下去總有一步(總假設匹配是存在的,不然就沒意思了)會出現這樣的情況:T中的前k-1(0<k<j)個字符與主串

中的字符都對上了,此時我拉只要比較k-1個字符之後的情況即可,如果不匹配就再移一步咯(你妹,這不是很笨麼?系噶),既然這種情況的出現是必然的,我們何不

一開始就把T串向右移動使T串的第K個字符T[k]與S[i]比較呢(靠,浪費這麼多力氣,這樣不是就可以不用回溯i了嗎?)。好!這都被我發現了(開玩笑,kmp他們早就知

道了,我也是抄下吧了),我就假設匹配進行到”T[0]……T[j-1]" = “S[i-j]……S[i-1]”時,又假設把T串向右移動步使得T串的第k個字符與S[i]比較時有“T[1]……T[k-1]” = “S[i-k+1]……S[i-1]”,結合前式我們可以輕易推出“T[0]……T[k-1]” = “T[j-k]……T[j-1]”(這式到後面有用,這裏可以無視先)。由於”T[0]……T[j-1]" = “S[i-j]……S[i-1]”,我們只需繼

續進行比較T[k] 與S[i],如果他們相等,就繼續比較T[k+1] 與S[i+1],如果他們不相等,則再以同樣的方法向右移動。現在我們又又假設next[j] = k 表示當T也就是子串的第i個字

符與主串不匹配時,我們像上面所講的那樣把T子串向右移動K步,然後可以繼續比較。現在剩下的問題是怎麼求出對應的next[j];

先定義:next[j] = -1 當 j = 0時;

             next[j] = k 當T[j]不能匹配時須把T串向右移動的距離(0 <k <j,這裏的k必然是可能的最大的,因爲這是我們一步一步移動T串第一次達到這樣情況時的k)

            next[j] = 0  除上面之外的情況


現在開始計論怎麼去求next[i]:

          先來看式:“T[0]……T[k-1]” = “T[j-k]……T[j-1]”(之前就說過他有用,現在來了),當達到這種情況時,k是唯一最大的,即不存在k1 〉k使:

             “T[0]……T[k1-1]” = “T[j-k1]……T[j-1]”,這在定義也說過。所以可以看出next[j]的取值只與子串T自身有關而與主串S無關(這點很重要),也就是我們要求的是

當T[j] != S[i]時使“T[0]……T[k-1]” = “T[j-k]……T[j-1]”的最大值next[j] = k;

             !!!注意現在我們的問題變成了另一個:求對於子串的每一個j對應的next[j]值這個值是與主串完全無關的,下面我們看下圖哈: 

   

              圖的數字僅代表們置,不是字符,如編號1.的圖,T串的字符"“T[0] ……T[6]” = “T[1]……T[7]”,表示next[8] = 7;那麼next[9]是什麼呢?如果T[7] = T[8],則有

“T[0] ……T[7]” = “T[1]……T[8]”,可以推得next[9] = 8;如果不等只能把下面的那行向右移一步如圖2,期待着"“T[0] ……T[6]” = “T[1]……T[8]”,如果成立則next[9] = 7;

如果也不成立,照此類推直到連“T[0]” = "T[8]",都不成立則next[9] = 0;到這裏不識有沒有意識到這同最初的兩個串匹配很相似呢!!!其實就是可以看作成主串是T

子串也是T的一個匹配,而當前情況下也就是“T[0]……T[k-1]” = “T[j-k]……T[j-1]”,要求nesxt[j+1]的值,只要按前面的方法(講兩個字符串匹配時),匹配就可以

得到next[j+1];由期定義出發就可以先預處理好next[i];用一個數組來保存對應的每一個next[]值;

                               以上只是個人愚見,大牛路過求指點

發佈了67 篇原創文章 · 獲贊 6 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章