KMP演算法中關於next陣列的探究
一、KMP演算法簡單介紹
KMP演算法是字串匹配演算法的一種,相對於樸素的字串匹配演算法而言,可以大大避免重複遍歷的情況。此演算法可以在O(n+m)的時間數量級上完成字串匹配操作。
二、神奇的next陣列
關於KMP演算法的原理和實現,書上或者百度一下都可以找到,我在這裡就不羅嗦那麼多了,直接切入主題(next陣列)。
我們設主串S=abcabcabca,模式串p=abcabx。
KMP第一趟匹配:
i=6
S : a b c a b c a b c a
位置 : 1 2 3 4 5 6 7 8 9 10
P : a b c a b x
位置 : 1 2 3 4 5 6
j=6
第一次匹配到第6個位置的時候失敗了,按照樸素的演算法,i要回溯到第2個位置,j要回溯到第1個位置重新匹配。KMP的話,主串中的i是不會回溯,模式串中的j回溯也不會回溯到第1個位置。注意這裡是關鍵,i不用回溯就可以完成整個字串的匹配。為什麼i不需要回溯呢?我們先留下這個疑問。
我們把匹配成功的前5個字元研究一下。
1位置的字首子串為:a , ab , abc , abca
5位置的字尾子串為:bcab , cab , ab , b
我們觀察發現兩組裡面都有一個ab,你能看出點什麼東西麼,好的,先不管這個。
我們就按照樸素的演算法來看,i回溯到第2第3位置都會在前5個字元中匹配失敗。
樸素匹配:
i=4
S : a b c a b c a b c a
位置 : 1 2 3 4 5 6 7 8 9 10
P : a b c a b x
位置 : 1 2 3 4 5 6
j=1
當回溯到第4個位置的時候,成功匹配的字元為ab,然後再去判斷S串的第6個字元和P串的第3個位置。這個然後我們先不管,觀察S中和P匹配的ab,在第一趟匹配的時候S中的ab是和P中前5個字元的最後兩個匹配的,而這一次匹配則是和P中前兩個字元匹配的。能發現點什麼東西麼?
不需要讓i回溯到之前的位置重新匹配,只需要找到在P串前5個字元中第一個位置的字首子串和最後一個位置的字尾子串相等並且串長最大的那一對子串,讓j指向字首子串最後一個字元的下一個位置3,和i所指向的6進行比較。往後遇見不匹配的時候採取和這個一樣的方法。
KMP第二趟匹配:
i=6
S : a b c a b c a b c a
位置 : 1 2 3 4 5 6 7 8 9 10
P : a b c a b x
位置 : 1 2 3 4 5 6
j=3
這個時候就需要next陣列的建立了,next[6]儲存的就是前5個字元組成的字串中的第一個位置的字首子串和最後一個位置的字尾子串相等並且串長最大的那一對子串的最後一個字元的下一個位置,也就是3,也就是和P串中第3個位置匹配。
寫到這裡,next陣列應該可以得出來了。
具體程式碼怎麼得出來的,書上面都有。。那個應該不難。
對於next陣列還有一個優化,《嚴書》上講的很清晰。
三、next陣列在ACM中的應用
直接用KMP演算法真的去匹配兩個字串其實很少見,除非字串裡的字符集範圍很小,或字元重複數量過多,用KMP可大減少時間,否則一般都是直接樸素匹配。
kmp演算法在ACM中並不大可能用來直接用,主要有用的是對它的理解和它的精華部分----求 next陣列,這個的一個用途就是確定重複子串,具體參見 poj2406,poj1961,poj2752。
void get_next(string s,int next[])
{
int length=s.length();
int i=0,j=-1;
next[0]=-1;
while(i<length)
{
if(j==-1||s[i]==s[j]) /*s[i]表示字尾的單個字元*/
/*s[j]表示字首的單個字元*/
{
++i;
++j;
next[i]=j;
}
else
j=next[j]; /*若j值不相同,則j值回溯*/
}
}
關於 KMP 演算法 b站的一個視訊不錯
相關文章
- 關於 KMP next 陣列的應用KMP陣列
- KMP演算法的Next陣列詳解KMP演算法陣列
- KMP演算法中我對獲取next陣列的理解KMP演算法陣列
- KMP演算法next陣列的深入理解KMP演算法陣列
- KMP演算法的next、next value陣列的手工計算KMP演算法陣列
- kmp 演算法簡介及 next 陣列推導KMP演算法陣列
- KMP演算法以及優化(程式碼分析以及求解next陣列和nextval陣列)KMP演算法優化陣列
- KMP演算法的next、next value陣列程式碼實現及POJ3461KMP演算法陣列
- [資料結構]KMP演算法(含next陣列詳解)資料結構KMP演算法陣列
- POJ 2406-Power Strings(重複子串-KMP中的next陣列)KMP陣列
- BZOJ 3670 [Noi2014]動物園 (KMP next陣列應用)KMP陣列
- POJ 2752+KMP+利用next陣列性質求出所有相同的字首和字尾KMP陣列
- 關於陣列去重陣列
- java陣列記憶體的探究Java陣列記憶體
- vue陣列操作遇到坑-關於陣列操作Vue陣列
- 關於在類陣列中使用陣列方法陣列
- bash指令碼中的普通陣列和關聯陣列指令碼陣列
- vue 關於陣列和物件的更新Vue陣列物件
- 關於字典和陣列的疑問陣列
- 演算法找陣列中的特定元素演算法陣列
- 關於new Object的探究Object
- 演算法陣列中降序數列的最大長度演算法陣列
- 關於 JS 陣列,物件 length 使用的坑JS陣列物件
- 關於位元組陣列QByteArray陣列
- 關於javascript中陣列元素刪除問題的討論 (轉)JavaScript陣列
- 陣列演算法-差分陣列陣列演算法
- 演算法基礎:動態規劃陣列中滾動陣列的使用演算法動態規劃陣列
- Java中陣列及相關類的使用Java陣列
- LeetCode 關於陣列的相對排序LeetCode陣列排序
- JavaScript關於陣列的一些方法整理JavaScript陣列
- 深度理解vue 關於陣列和物件的更新Vue陣列物件
- 關於IOS物件的小事的探究iOS物件
- PHP 陣列current和next用法分享PHP陣列
- 演算法-兩個排序陣列的中位數演算法排序陣列
- 陣列的基本演算法陣列演算法
- 【譯】關於JavaScript 陣列你應該知道的事情JavaScript陣列
- 【面試系列】之五:關於字串以及陣列的操作面試字串陣列
- c語言關於陣列的簡單運算C語言陣列