KMP演算法詳講

2021-06-01 18:30:46 字數 2655 閱讀 6119

一.  簡單匹配演算法

先來看乙個簡單匹配演算法的函式:

int index_bf ( char s [ ], char t [ ], int pos )

else

j = nextval[j]; //子串移動到第nextval[j]個字元和主串相應字元比較

}}

下面是我寫的kmp模式匹配程式,各位可以測試一下。

#include#include#include#includeusing namespace std;

#define n 100010

char str1[n], str2[n];

int nextval[n];

int lens, lenp;

void getnext(const char *p, int nextval) //字首函式(滑步函式)

else

j = nextval[j]; //子串移動到第nextval[j]個字元和主串相應字元比較

} cout<<"字首函式為:"<

五.其他表示模式值的方法

上面那種串的模式值表示方法是最優秀的表示方法,從串的模式值我們可以得到很多資訊,以下稱為第一種表示方法。第二種表示方法,雖然也定義next[0]= -1,但後面絕不會出現 -1,除了next[0],其他模式值next[j]=k(0≤k下面給出幾種方法的例子:

表一。下標01

2345

678t

abab

caab

c(1) next-10

-102-1

102(2) next-10

0120

112(3) next01

0130

213第三種表示方法,在我看來,意義不是那麼明了,不再討論。

表二。下標01

234t

abca

c(1)next-10

0-11(2)next-10

001表三。下標0

1234

567t

adca

dcad

(1)next-10

0-100

-10(2)next-10

0012

34對比串的模式值第一種表示方法和第二種表示方法,看錶一:

第一種表示方法next[2]= -1,表示t[2]=t[0],且t[2-1] !=t[0]

第二種表示方法next[2]= 0,表示t[2-1] !=t[0],但並不管t[0] 和t[2]相不相等。

第一種表示方法next[3]= 0,表示雖然t[2]=t[0],但t[1] ==t[3]

第二種表示方法next[3]= 1,表示t[2] =t[0],他並不管t[1] 和t[3]相不相等。

第一種表示方法next[5]= -1,表示t[5]=t[0],且t[4] !=t[0],t[3]t[4] !=t[0]t[1],t[2]t[3]t[4] !=t[0]t[1]t[2]

第二種表示方法next[5]= 0,表示t[4] !=t[0],t[3]t[4] !=t[0]t[1] ,t[2]t[3]t[4] !=t[0]t[1]t[2],但並不管t[0] 和t[5]相不相等。換句話說:就算t[5]==』x』,或 t[5]==』y』,t[5]==』9』,也有next[5]= 0 。

從這裡我們可以看到:串的模式值第一種表示方法能表示更多的資訊,第二種表示方法更單純,不容易搞錯。當然,用第一種表示方法寫出的模式匹配函式效率更高。比如說,在串s=「adcadcbdadcadcad 9876543」中匹配串t=「adcadcad」, 用第一種表示方法寫出的模式匹配函式,當比較到s[6] != t[6] 時,取next[6]= -1(表三),它可以表示這樣許多資訊:s[3]s[4]s[5]==t[3]t[4]t[5]==t[0]t[1]t[2],而s[6] != t[6],t[6]==t[3]==t[0],所以s[6] != t[0],接下來比較s[7]和t[0]吧。如果用第二種表示方法寫出的模式匹配函式,當比較到s[6] != t[6] 時,取next[6]= 3(表三),它只能表示:s[3]s[4]s[5]== t[3]t[4]t[5]==t[0]t[1]t[2],但不能確定t[6]與t[3]相不相等,所以,接下來比較s[6]和t[3];又不相等,取next[3]= 0,它表示s[3]s[4]s[5]== t[0]t[1]t[2],但不會確定t[3]與t[0]相不相等,即s[6]和t[0] 相不相等,所以接下來比較s[6]和t[0],確定它們不相等,然後才會比較s[7]和t[0]。是不是比用第一種表示方法寫出的模式匹配函式多繞了幾個彎。

所以,我們使用的話,盡量還是使用第一種方法好。

六.後話--kmp的歷史

cook於2023年證明的乙個理論得到,任何乙個可以使用被稱為下推自動機的計算機抽象模型來解決的問題,也可以使用乙個實際的計算機(更精確的說,使用乙個隨機訪問機)在與問題規模對應的時間內解決。特別地,這個理論暗示存在著乙個演算法可以在大約m+n的時間內解決模式匹配問題,這裡m和n分別是儲存文字和模式串陣列的最大索引。knuth 和pratt努力地重建了 cook的證明,由此建立了這個模式匹配演算法。大概是同一時間,morris在考慮設計乙個文字編輯器的實際問題的過程中建立了差不多是同樣的演算法。這裡可以看到並不是所有的演算法都是「靈光一現」中被發現的,而理論化的電腦科學確實 在一些時候會應用到實際的應用中。

KMP匹配詳講以及AC自動機模板

對於初學字串的人來說 kmp演算法算是乙個比較難以理解的演算法,但是它在字串匹配問題的效率中是很高的。核心思想 匹配過程中 對於每一次失敗的匹配所提供的有用資訊加以利用。abcabcabcd和abcabcd進行匹配 匹配到 abcabc a abcabc d的時候匹配失敗我們可以直接跳轉到 匹配 a...

堆排序詳講

堆排序的時間,主要由建立初始堆和反覆重建堆這兩部分的時間開銷構成,它們均是通過呼叫heapify實現的 o n logn 排序 heapsort 是指利用堆積樹 堆 這種資料結構所設計的一種排序演算法,它是選擇排序的一種。可以利用陣列的特點快速定位指定索引的元素。堆分為大根堆和小根堆,是完全二叉樹。...

mapreduce shuffle 講的很詳細

mapreduce 是現今乙個非常流行的分布式計算框架,它被設計用於平行計算海量資料。第乙個提出該技術框架的是google 公司,而google 的靈感則來自於函式式程式語言,如lisp,scheme,ml 等。mapreduce 框架的核心步驟主要分兩部分 map 和reduce。當你向mapre...