KMP算法的核心,是一个被称为部分匹配表(Partial Match Table)的数组以及next数组求解
KMP算法的核心,是一個被稱為部分匹配表(Partial Match Table)的數組。我覺得理解KMP的最大障礙就是很多人在看了很多關于KMP的文章之后,仍然搞不懂PMT中的值代表了什么意思。這里我們拋開所有的枝枝蔓蔓,先來解釋一下這個數據到底是什么。
對于字符串“abababca”,它的PMT如下表所示:
就像例子中所示的,如果待匹配的模式字符串有8個字符,那么PMT就會有8個值。
我先解釋一下字符串的前綴和后綴。如果字符串A和B,存在A=BS,其中S是任意的非空字符串,那就稱B為A的前綴。例如,”Harry”的前綴包括{”H”, ”Ha”, ”Har”, ”Harr”},我們把所有前綴組成的集合,稱為字符串的前綴集合。同樣可以定義后綴A=SB, 其中S是任意的非空字符串,那就稱B為A的后綴,例如,”Potter”的后綴包括{”otter”, ”tter”, ”ter”, ”er”, ”r”},然后把所有后綴組成的集合,稱為字符串的后綴集合。要注意的是,字符串本身并不是自己的后綴。
有了這個定義,就可以說明PMT中的值的意義了。PMT中的值是字符串的前綴集合與后綴集合的交集中最長元素的長度。例如,對于”aba”,它的前綴集合為{”a”, ”ab”},后綴 集合為{”ba”, ”a”}。兩個集合的交集為{”a”},那么長度最長的元素就是字符串”a”了,長 度為1,所以對于”aba”而言,它在PMT表中對應的值就是1。再比如,對于字符串”ababa”,它的前綴集合為{”a”, ”ab”, ”aba”, ”abab”},它的后綴集合為{”baba”, ”aba”, ”ba”, ”a”}, 兩個集合的交集為{”a”, ”aba”},其中最長的元素為”aba”,長度為3。
好了,解釋清楚這個表是什么之后,我們再來看如何使用這個表來加速字符串的查找,以及這樣用的道理是什么。如圖 1.12 所示,要在主字符串"ababababca"中查找模式字符串"abababca"。如果在 j 處字符不匹配,那么由于前邊所說的模式字符串 PMT 的性質,主字符串中 i 指針之前的 PMT[j ?1] 位就一定與模式字符串的第 0 位至第 PMT[j?1] 位是相同的。這是因為主字符串在 i 位失配,也就意味著主字符串從 i?j 到 i 這一段是與模式字符串的 0 到 j 這一段是完全相同的。而我們上面也解釋了,模式字符串從 0 到 j?1 ,在這個例子中就是”ababab”,其前綴集合與后綴集合的交集的最長元素為”abab”, 長度為4。所以就可以斷言,主字符串中i指針之前的 4 位一定與模式字符串的第0位至第 4 位是相同的,即長度為 4 的后綴與前綴相同。這樣一來,我們就可以將這些字符段的比較省略掉。具體的做法是,保持i指針不動,然后將j指針指向模式字符串的PMT[j ?1]位即可。
簡言之,以圖中的例子來說,在 i 處失配,那么主字符串和模式字符串的前邊6位就是相同的。又因為模式字符串的前6位,它的前4位前綴和后4位后綴是相同的,所以我們推知主字符串i之前的4位和模式字符串開頭的4位是相同的。就是圖中的灰色部分。那這部分就不用再比較了。
有了上面的思路,我們就可以使用PMT加速字符串的查找了。我們看到如果是在 j 位 失配,那么影響 j 指針回溯的位置的其實是第 j ?1 位的 PMT 值,所以為了編程的方便, 我們不直接使用PMT數組,而是將PMT數組向后偏移一位。我們把新得到的這個數組稱為next數組。下面給出根據next數組進行字符串匹配加速的字符串匹配程序。其中要注意的一個技巧是,在把PMT進行向右偏移時,第0位的值,我們將其設成了-1,這只是為了編程的方便,并沒有其他的意義。在本節的例子中,next數組如下表所示。
具體的程序如下所示:
好了,講到這里,其實KMP算法的主體就已經講解完了。你會發現,其實KMP算法的動機是很簡單的,解決的方案也很簡單。遠沒有很多教材和算法書里所講的那么亂七八糟,只要搞明白了PMT的意義,其實整個算法都迎刃而解。
現在,我們再看一下如何編程快速求得next數組。其實,求next數組的過程完全可以看成字符串匹配的過程,即以模式字符串為主字符串,以模式字符串的前綴為目標字符串,一旦字符串匹配成功,那么當前的next值就是匹配成功的字符串的長度。
具體來說,就是從模式字符串的第一位(注意,不包括第0位)開始對自身進行匹配運算。 在任一位置,能匹配的最長長度就是當前位置的next值。如下圖所示。
求next數組值的程序如下所示:
至此,KMP算法就全部介紹完了。
總結
以上是生活随笔為你收集整理的KMP算法的核心,是一个被称为部分匹配表(Partial Match Table)的数组以及next数组求解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 笔记:python设计模式
- 下一篇: Pandas中的元素替换