算法學習系列之二章---KMP算法圖解

一、簡介

        KMP算法,首先與BF算法做比較…….(此處略去簡介200字,至於哪200字,網上隨便找一篇講KMP算法的基本上都會先講樸素算法);

二、題外話

        記得大二的時候,DS課程設計就是實現KMP算法,當時也沒弄太清楚(或者弄清楚了也忘記了),就知道在網上搜到了代碼,然後就好用!然而這幾天抱着深入學習的態度,反而有點暈,可能年紀大了吧!在網上找到很多資料把我看的直接拔電源了都!我想說的是,根據自己這兩天在網上的搜索可知,很多關於KMP算法的介紹的文章,篇幅都比較長,沒有心情看下去,而且感覺不能突出重點,我只想問,有那麼複雜嗎?也許是優化版很多吧。那麼,接下來,我們就用圖標的方式,來分析一下,這個算法到底有多複雜。

三、主題

        主題沒有代碼,只有圖表。下面,我們就以


爲例,我們來學習這個算法的思想。

1. 關於Next數組

什麼是Next數組,Next數組時幹嘛的呢?不知道?那就自己搜搜去。

這個算法的關鍵,就是Next數組的構造與使用,使用當然就很簡單,主要的是來看看構造。


我們將KMP原始算法 與 KMP改進算法對比着來看。

原始算法

1. Next[0] = -1:因爲由失配發生時,模式串跳轉的位置爲:右移動j - Next[j]長度.

                       若在首位置失配,只能右移一位,類似樸素算法,所以要右移一位,又要將這種情況套入:j - Next[j] 因此,只能爲-1

2. Next[j] 的值爲:

                         若存在一個k,使得:模式串的前 Next[0],Next[1]... Next[k-1]) 個字符與Next[j-k],Next[j-k+1]Next[j-1]相等,則    Next[j] = k;

                         若不存在一個k,使得:模式串的前 Next[0],Next[1]... Next[k-1]) 個字符  與   Next[j-k],Next[j-k+1]Next[j-1]相等,則    Next[j] = 0;

改進算法:

1. 1.Next[0] = -1;同上

2. .Next[j] 的值爲:

                          若存在一個k,使得:模式串的前 Next[0],Next[1]... Next[k-1]) 個字符  與   Next[j-k],Next[j-k+1]Next[j-1]相等,並且 Next[k] != Next[j]    則   Next[j] = k否則若Next[k] == Next[j]   則   Next[j] = -1;

                         若不存在一個k,使得:模式串的前 Next[0],Next[1]... Next[k-1]) 個字符  與   Next[j-k],Next[j-k+1]Next[j-1]相等,並且 Next[0] == Next[j]    則   Next[j] = -1否則若Next[0] != Next[j]   則   Next[j] = 0;

 

根據以上原則,我們來計算一下我們的模式串的Next函數



//根據以上的圖我們知道Next數組的計算了,至於代碼,我就只貼一下改進算法的好了
void GetNextval(const SWORD *pswPattern, SDWORD *psdNext, SDWORD sdLength ) 
{ 
	// 求模式串pswPattern的next函數值並存入數組 next。
	SDWORD j = 0, k = -1; 
	psdNext[0] = -1; 
	while ( j < sdLength ) { 
		if ( k == -1 || pswPattern[j] == pswPattern[k] ) { 
			++j; ++k; 
			if ( pswPattern[j] != pswPattern[k] ) {
				psdNext[j] = k; 
			}
			else {
				psdNext[j] = psdNext[k]; 
			}
		}
		else {
			k = psdNext[k]; 
		}
	}
}

OKNext數組我們求出來了,我們再列個表格來展示一下兩種算法的匹配過程吧

原始算法



改進算法:



四、結語

          Sunday算法是另外一種匹配算法,據說比KMP要高效,還沒學習,等以後學習了再加上吧。《算法導論》上關於KMP的內容基本上都是一些理論證明,如果數學比較好的童鞋可以看看,如果只是爲了應用,那麼,網上隨便找到的完整代碼都是可以用的了。

可能我的表述有些簡單,或者哪裏表述的不對,還請諸位指正,因爲這兩天有點懵圈了,難免有疏漏或者理解錯誤之處,敬請原諒。


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