直接把作業帖上來是不是有點不太公道呀。。。
無所謂啦反正各位看着開心就行
KMP算法
對於模式串$P$,建立其前綴函數$ N$ ,其中$N [q] $ 表示在$P$中,以$q$位置為結束的可以匹配到前綴的最長后綴的長度(也可以理解為那個前綴的結束位置),在匹配中,若$P[i]$與$S[j]$失配,則令$i=N [i-1] +1$ ,否則$i=i+1,j=j+1$
現考慮如何構造$N$ ,設當前以計算出$N[1..i-1]$ ,則令$k=N[i-1]$ ,若 $P[k+1]=P[i]$,則令$N[i]=k+1$ ,否則令$k=N[k]$ 。重復上述過程,直至找到$N[i]$
可證該算法能在$\Theta(|P|) $ 的時間內構造出前綴函數$N$ ,在$\Theta (|S|)$ 的時間內完成匹配,總的時間復雜度為$\Theta(|S|+|P|)$
KMP算法的正確性證明
先證明匹配過程的正確性:
在過程中,若$P[1..q]$ 與$S[s+1...s+q]$ 匹配,而$P[q+1]$與$S[s+q+1]$ 失配,那么由$N$的定義可立即得出$P[1..N[q]]$ 與 $S[s+q-N[q]+1...s+q]$ 匹配,而$S[1...t]$與$S[s+q-t+1...s+q]$ 失配$(N[q]<t<q)$ ,即只需檢驗$P[N[q]+1]$ 與$S[s+q+1]$ 的匹配情況即可,匹配過程的正確性即可得證。
接下來證明前綴函數$N$計算的正確性:
令$N^*[q]= \{N[q],N^{(2)}[q],…,N^{(t)}[q]\}$ 其中$N^{(t)}[q]=N^{(t-1)}[q],N^{(0)}[q]=N[q]$ ,那么$N^*[q]$ 為以q位置為結束的可以匹配到前綴的后綴的所有長度(即匹配到所有前綴的位置),同時有$N[q]-1\in N^*[q-1]$ ,因此只需從大到小枚舉$N^*[q-1]$ 中的元素並通過判斷即可得出$N[q]$ 。
KMP算法的時間復雜度證明
在匹配時:$i,j$增長了$|S|$ ,而在$i=N[i-1]+1$ 中,$i$ 至少減少1,即該語句至多執行了$|S|$次,因此時間復雜度為$\Theta(|S|)$。
構造前綴函數$N$ 時: 我們考慮k的變化,我們可以得到,在每次$k=N[k]$ 中,$k$ 至少減少1,又因為$k$隨$i$增加了$|P|$次,即該語句至多執行$|P|$ 次,因此時間復雜度為$\Theta(|P|)$ 。
因此總的時間復雜度為$\Theta(|S|+|P|)$ 。
KMP算法的優化
我們希望通過優化,為了減少失配的概率,因此提出如下改進:
在構造$N'$數組時,當$P[k+1]=P[i]$ 時,若$P[i+1]=P[k+2]$ 則$N'[i]=k+1$ 否則$N'[i]=N'[k+1]$ 。
該優化的正確性證明
在匹配時,我們發現,若$P[q+1]$ 與$S[s+q+1]$失配,同時$P[q+1]=P[N^{(t)}[q]+1]$ ,則$P[N^{(t)}[q]+1]$一定與$S[s+q+1]$ 失配,因此若$P[N[q]+1]=P[q+1]$ ,則該比較一定失配,無需考慮。
在該優化中,由該函數的遞歸求法可得,$N'[q]=max\{N^*[q]且P[q+1]\neq P[N^{(t)}[q]+1]\}$ ,因此$N'[q]$ 依舊能枚舉完所有可能匹配的前綴,同時減少失配概率。
該優化對算法空間與時間復雜度的影響
由於該優化只是改變了N數組的構造方法,因此對空間復雜度無影響。
時間復雜度的證明同KMP的證明,可得對最壞情況下的時間復雜度無影響
由於該算法避免了出現$P[N[q]+1]=P[q+1]$的情況,因此對於有較多重復子串的模式串有較好的優化效果(如aaaab,abcabcabcd)