KMP演算法個人感悟

2022-07-16 01:09:14 字數 2790 閱讀 1631

既然來到了這,那也一定是被kmp困惑了一陣的小夥伴。雖然這篇文章也不一定讓你能看懂,但是這算是我自己個人對於kmp的最直接的理解,也許不好,也許有誤,望大佬指出。

對於串的模式匹配的演算法很多,當然最簡單就是暴力破解法(也即是bf演算法),由此我們從這開始引入

bf演算法原理就是將主串和模式串依次進行比較,若遇到不同的時候,主串和模式串都會回溯(也許開始這會有點迷,但是沒影響,後面自然會理解)

我們將模式串和主串開始依次比較,第乙個都不相同,很簡單的就是直接用模式串和第乙個和主串的第二個開始比較,如下

就這樣依次比較,我們會發現前四個都是不行的(包括其中的乙個括號),因此我們就直接從第五個開始比較

我們會發現從模式串的a到b都是相同的,所以直接跳過到不同的位置比較時吧

這是主串和模式串已經出現了不同,於是我們要開始考慮下一步怎麼做。

很容易就會想到我們再拿模式串的第乙個和主串剛才最開始比較的地方的下乙個重新開始比較,如下

這一步的這個過程就叫做回溯

但是我們會發現乙個問題因為我們開始匹配成功時已經就確定了前面的位置的字母了,我們將主串回溯和模式串的開頭重新比較肯定會失敗,這就會浪費很多的時間。那我們仔細的觀察就會發現,當我們匹配失敗後可以直接將模式串的第三個和主串失配的位置重新開始比較,這樣就不用回溯主串的指標了,也不用將模式串的指標回溯到頭了,可以節約不少時間。這也就是kmp演算法的思路。

但是為什麼要從模式串的第三個位置開始比較呢?

我們想想這幅圖

當我們匹配到這個地步了,發現不匹配,相當於我們前面的匹配成功的主串是和模式串相同的,也就是說我們是知道了這一部分主串的樣子的,我們確切的知道它們每個位置的字元,因此肯定不會去拿乙個不一樣的字元去比較,這就是浪費時間的作為。所以我們就會尋找其中相同的子串,並根據這個將模式串指標回溯到合適的位置進行比較。

如上面這中情況,我們肯定就會從模式串的第三個位置開始比較,因為我們會發現前面的部分其中有字首ab和字尾ab是相同,因此如下圖

kmp演算法

到了這裡,我們就可以認真的分析kmp演算法的步驟了

首先,我們會將模式串和主串依次比較

然後,若我們遇到了匹配失敗的時候,就保持主串的指標不動,盡可能的將模式串向右滑動(即回溯模式串的指標i),回溯到**呢就要看後面的next陣列,即回溯到對應的next陣列的值那裡

最後,直到匹配成功或者主串長度不夠匹配失敗

那麼就還有最後乙個也是最重要的乙個問題了:匹配失敗的時候到底將i回溯到哪個位置,怎麼計算,計算機肯定不會像我們大腦那麼去思考,所以需要我們告訴它

我們解決這個回到**的問題,我們發現我們思考的時候是找到了前字尾的最長公共元素長度,那我們就來思考如何尋找這個,然後告訴計算機不就行了嗎

注:這裡的前字尾表示是小於串本身長度的

舉例:對於乙個串ababc

開始尋找

就會得到這麼乙個公共最長前字尾的表

但是這也會有一些不對,例如我們匹配到了c這一步失配,這個表會讓我們再次從0開始比較,但這顯然不對,因為前面都是ab,因此我們應當從第三個開始比較,所以kmp演算法基於這個表做了操作,也就形成了大家所知的next陣列

next陣列

對於next陣列,我們第乙個元素肯定是為0,第二個元素是為1(先別疑惑,聽我慢慢道來)(當然再提醒一下這裡的陣列是從1號位置開始存放資料的)

大家想想,若當前的主串比較的位置和模式串的第乙個位置都不匹配怎麼辦?當然bf是直接將主串指標j後移,然後比較。但kmp演算法的描述裡失配時j時保持不動的,模式串指標i回溯。因此由於第乙個元素裡面值為0,所以i會等於0,但是0號位置並沒有元素,因此當i=0時我們就將j和i都後移一位,是不是就相當於j直接向後移一位了呢。

那麼第二位為什麼一定為1呢?

不妨我們再來假設一下,如果第二位時匹配失敗我們應該怎麼做呢?其實也就很簡單了,我們就保持主串不動,將模式串再從1開始比較起走,因此第二位肯定為1

那麼整個next陣列怎麼求呢?

其實到了這裡就很簡單了,我們已經明確了第一位和第二位是0和1,那麼從第三位開始,值就是前面的最長公共前字尾長度+1

例如

蟹蟹

KMP演算法 感悟

先說下我的教材 資料結構 c語言描述 耿國華 主編 第四章 串 其中有個模式匹配演算法,一般的演算法看懂之後,在網上找了kmp演算法看,看了老長時間才看明白,真高興,和大家分享下 define maxlen 40 include include typedef struct sstring int ...

KMP演算法感悟

學了幾天kmp演算法。開始覺得有點難懂,但是堅持下來了,最終搞明白了,還是蠻開心的。所以寫點kmp演算法的感悟 1 next陣列只和模式串本身有關和文字串是無關的,因為next表示的是當匹配失敗後模式串要回溯到哪個位置。2 next陣列儲存的資料是用來當模式串與主串不匹配的時候要模式串回退到第幾個字...

KMP 演算法(個人理解)

相信大家看了 matrix67 的講解,一定已經知道了 kmp 演算法是怎麼回事,怎麼操作的,為什麼時間複雜度不高 這裡,我主要是分享我對 kmp 的理解 kmp 的精髓是什麼?這個東西,各自有個字的理解,很多人都覺得是避免了重複匹配,而我的理解是預處理 為什麼是預處理?你看看 kmp 的執行過程 ...