KMP算法的動態規划解說


理解我接下來所說的東西,需要大家懂得簡單的動態規划。

KMP大家都不陌生了,但是其中計算next數組總是搞不明白,我想有很多人和我一樣。所以這里用動態規划的思路去描述一下這個問題。

模式串P=c[1]c[2]......c[n]

先設幾個符號:

suffix(S): S的所有后綴的集合

prefix(S): S的所有前綴的集合

例如:suffix("abcd") = {"","d", "cd", "bcd"}

         prefix("abcd") = {"","a", "ab", "abc"}

看到,在這兩個集合都除去了"abcd"本身。

真對P定義next的意義:next[i]代表的意義是suffix(c[1]c[2]......c[i])與prefix(c[1]c[2]......c[i])兩個集合中最長相同串的長度(不包括串c[1]c[2]......c[i])。那么如何計算next呢?其實這個計算過程類似動態規划的轉移過程,從初始狀態,不斷的根據轉移方程計算,直至計算出所有的可達狀態。

那么狀態怎么定義?初始條件是什么?

設兩個游標p1,p2, p1,p2構成的位置對為狀態<p1,p2>,例如p1在i位置,p2在j位置,i<j,那么狀態<i, j>就代表c[1]c[2]......c[i]=c[j-i+1]c[j-i+2]......c[j],即串的前i個字符與后i個字符相同。之后我們根據<i,j>推出<i',j+1>。我們依次計算<i1, 1>,<i2,2>,......,<in,n>。設LMAX(<i, j>)=i,通過上面對next的定義,我們可知next[j]=MAX{LMAX(<i,j>)|0<=i<j}。

初始化的條件為 next[1] = LMAX(<0, 1>) = 0。假設我們當前所在的狀態為<i, j>,那么如何推出<i',j+1>呢?這必須得看c[i+1]與c[j+1]的關系,如果c[i+1]=c[j+1],那么我們到達<i+1,j+1>的狀態;如果c[i+1]!=c[j+1],那么我們得根據所有可能的<i', j>狀態,判斷c[i'+1]=c[j+1]是否成立,如果成立就到達<i'+1,j+1>狀態。那么,我們如何找到這些合法的<i',j>狀態呢?很慶幸,因為next數組中天然的保存了我們需要的信息。當我們到達<i,j>這個狀態並且發現c[i+1]!=c[j+1],那么下一個嘗試的狀態將是<next[i], j>,看看c[next[i]+1]=c[j+1]是否成立。而且我們發現,只要按照i,next[i],next[next[i]]......這樣下去找到第一個能夠符合轉移條件的狀態就OK了,如果沒有一個能夠使之轉移的狀態,就說明沒有一個前綴和當前的某個后綴是相等的,那么直接跳轉到<0, j+1>這個狀態。

舉個例子吧: S=abcababc

為了方便理解,在S前加一個通配符$

$abcababc          <0, 1>             next[1]=0
||

$abcababc          <0, 2>             next[2]=0
| | 

$abcababc          <0, 3>             next[3]=0
|  |

$abcababc          <1, 4>             next[4]=1
 |  | 

$abcababc          <2, 5>             next[5]=2
  |  |

下一步s[3]!=s[6],這將嘗試狀態<next[3],j>=<0,j>,使之轉移到下面的狀態

$abcababc          <1, 6>             next[6]=1
 |    | 

$abcababc          <2, 7>             next[7]=2
  |    |

$abcababc          <3, 8>             next[8]=3
   |    |

到此,有的同學又有疑問了,人家KMP定義的next[i]的意義和你的也不一樣呀。對,確實不一樣。

KMP中對next[i]的定義為:設文本串為T,模式串為P,p[i]!=T[j]時,應該用p[?]與T[j]進行比較。

對應於上例,得到的next數組值應為

KMP的next: -1 1 1 1 2 3 2 3
我們的next:  0 0 0 1 2 1 2 3

怎么通過我們的next獲取到正確的next呢?非常簡單,從后往前循環做next[i] = next[i-1]+1,之后next[1]=-1就哦了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM