/***摘自《大話資料結構》*/
/*t為字串,
next
為int
陣列,儲存
next值*/
void getnext(string t,int *next)
{int i,j;
i=1;j=0;next[1]=0;
while(i採取分段證明的辦法,證明j往區間(m,k)移動是不正確的,驗證移動到m(next[j]=m)的正確性。
在證明的過程中,都是假設j移動到某個位置之後,討論if判斷條件會成立。因為如果是不成立的話,程式流程又會轉移到j的移動,這樣我們就會陷入死迴圈。而且,這種假設,即if成立,在邏輯上也是成立的,就像遞迴函式一樣,只要一層是正確的,遞迴的肯定也沒問題。
首先觀察這個函式的**,我們可以獲得如下資訊:
(1) 若if成立,則i、j都加1;
(2) i的值為k,則next[k]已經有了結果,且在下一輪if之前j= next[k];
(3) 當要求next[k]的時候,if中的判斷條件是i=k-1;
證明:前提條件:假設next[k]=s,
即t[1]…[s-1]=t[k-s+1]…[k-1](1)
現求next[k+1]=?根據前面的結論,此時i=k,j=s。令next[s]=m.
現進行if判斷:
(1) 若條件成立,
即t[i]=t[j],也即t[k]=t[s],結合式(1),則有
t[1]…[s-1][s]=t[k-s+1]…[k-1][k] (2)
則next[k+1]=s+1,即**中的next[i]=j;繼續下一次if判斷。
(2) 若條件不成立,
即t[i] != t[j],則我們需要移動j。
假設向區間 (s , k) 移動,假使使j=s+1,滿足if條件,即t[k]=t[s+1],
根據**,則next[k+1]=s+2,意味著
t[1]…[s-1][s][s+1]=t[k-s]…[k-1][k] (3)
等式兩邊去掉末位,
t[1]…[s-1][s] =t[k-s]…[k-1] (4)
從這可以推出next[k]=s+1,與前面矛盾,所以j不能向前移(假若向前移動更多位的話,就會推出next[k]比s+1更大的值)
下面證明j向(m,s)區間移動是不行的。
已知條件:i=k,j=s,next(s)=m,next(k)=s,t[k]!=t[s],需證明移動到m+1是不行的。
現我們假設把j移動到m+1,而不是**中的m。
根據已知條件可以得到:
next(k)=s =>t[1]…[s-1]=t[k-s+1]…[k-1] (5)
next(s)=m =>t[1]…[m-1]=t[s-m+1]…[s-1] (6)
if判斷成立,t[k]=t[m+1],則得到next(k+1)=m+2,
t[1]…[m+1]=t[k-m]…[k] (7)
兩邊去掉右邊一位,則有t[1]…[m] =t[k-m]…[k-1] (8)
觀察(5),因為s>=m+1,所以k-m>=k-s+1,
所以t[1]…[m] =t[k-m]…[k-1]
= t[s-m]…[s-1] (由5)
從這裡可以推出,next(s)至少為m+1,與已知矛盾。
顯然,若移動到m+2等就可以得到更大的next(s)的值了。
接下來,我們證明移動j到next[j]的正確性。
設next[j]=m,此時j=s,next[s]=m,移動j到next[s]後,即j=m。
由next[s]=m有:
t[1]…[m-1] =t[s-m+1]…[s-1] (9)
判斷t[i]==t[j],即t[k]==t[m],條件成立之後,因為s>=m+1,所以
k-m+1>k-s+1,即t[k-m+1]在t[k-s+1]…[k-1][k]中。
取(1)中等式兩邊右邊的m-1項,得到:
t[s-m+1]…[s-1] =t[(k-1)-(m-1)+1]…[k-1]= t[k-m+1]…[k-1] (10)
又結合(9)(10)有
t[1]…[m-1] =t[k-m+1]…[k-1] (11)
結合t[k]==t[m],有
t[1]…[m-1][m]=t[k-m+1]…[k-1][k] (12)
從而next[k+1]=m+1,即**中的next[i]=j。由next的定義可知,j向(0,m)區間移動的話就得不到正確的next值,應為已經找到了j=m滿足要求,j值只能增大,減少就不符合定義。
至此,我們證明了把j回溯到大於m的任何位置都會得到錯誤的結論,且驗證了移動到m可以得到正確的結論。
KMP演算法中的next函式
kmp演算法詳解看 next i 表示當模式串t i 與主串失配時,模式串的索引回溯到next i 主串的索引不變 下面串的下標均從0開始 1 i 0 next i max k 0 k 證明模式串next函式的可行性 當t i 與 s j 失配時,即 t i s j 時 可得t 0.i 1 s j ...
KMP演算法中next函式的解析
今天花了半天的時間,終於把kmp演算法中的next函式整明白了 先看看next資料值的求解方法 位序 1 2 3 4 5 6 7 8 模式串 a b a a b c a c next值 0 1 1 2 2 3 1 2next陣列的求解方法是 1.第一位的next值為0 2.第二位的next值為1 後...
KMP演算法中next函式的解析
今天花了半天的時間,終於把kmp演算法中的next函式整明白了 先看看next資料值的求解方法 位序 1 2 3 4 5 6 7 8 模式串 a b a a b c a c next值 0 1 1 2 2 3 1 2 next陣列的求解方法是 1.第一位的next值為0 2.第二位的next值為1 ...