KMP演算法的細節問題

2022-07-21 07:36:10 字數 2063 閱讀 6963

想必,很多人都知道d.e.knuth與v.r.pratt和j.h.morris同時提出所謂的狂拽酷炫屌炸天的kmp演算法,在對字串的匹配(或是字串的查詢)方面表現出比較好的效率,該演算法對brute-force演算法的較大改進,具體地講就是消除了主串指標的回溯,從而使匹配的時間複雜度從o(n2)降低到o(n+m)(n為文字串的長度,m為模式串長度)。其傳神之處在於在於針對模式串構造的乙個nest陣列(該陣列只與模式串有關)。

kmp演算法、增強kmp演算法

a:對於某一字串來說,約定從第乙個字元開始向後的連續若干長度的字串為字首字串,同理從最後乙個字元開始向前的連續若干長度的字串為字尾字串

case 1:對於字串「qcer」而言,」qc「為長度為2的字首字串,」er「為長度為2的字尾字串。特殊的,「qcer」既是字首字串又是字尾字串。

a:nest[k]定義為在模式串中下標為k位置的前面所有字串中所有字首字串與字尾字串相等的情況中最長的匹配長度。but,如這等讓你我眩暈的表達,不看也罷!一圖勝前言!

對於nest[2],下標為2即字元『c』前面的字串為「ca」,故沒有字首字串與字尾字串相等的情況,其值當然為0。

對於nest[3],下標為3即字元『l』前面的部分為「cac」,故只有字首字串「c」與字尾字串「c」,其值為1。

其實這個空降的nest陣列是有點不好理解的,至少理解很不深刻!

so,下面再給出一種通用的理解方式:

對於求nest[7]的值,更直觀的過程可以如下圖。

即把字串下標為7即字元『m』之前的字串「cacldca」從右往左部逐步推進,整個過程在步驟2位置取得正確的值2。步驟3到步驟6中任意一步重疊部分均不能完全匹配(如果有重疊部分完全匹配的情況,那麼必然其值比2大)。故不能取到比2更大的值。

首先,理解這個過程度對後面核心演算法的匹配過程相當重要。其次,真正求nest陣列的值當然不會用這樣low的方法。

如果匹配的過程看做模式串從主串的開始處向右」移動「+匹配的過程,那麼kmp不在只是逐步移動,而且還能」跨越式「移動。

a:先上圖!

位置1中,n和m不等,直接跨越過4個字元到位置2處,中間都不用比較就知道不會有匹配成功情況。但是為什麼可以這樣?再上圖!

因為在位置3到位置6之間絕對不會出現重疊部分相匹配的情況,如果出現那麼nest[7]的值將定會是乙個比2大的數,這與nest的定義是相悖的,所以處理3到6的步驟可以自信地跨越!!

a:還是上圖!

k為位置j的最長前、字尾匹配串3的下乙個位置,同理,m為k的最長前、字尾匹配串1的下乙個位置。

nest[j]已知,即對j位置前面的所有串,字首串3和字尾串4相等且最長;k在j前面,nest[k]也已知,同理,k前面的所有串,字首串1和字尾串2相等且最長。

求nest[i]分兩種情況:

1) arr[k] = arr[j];nest[i] = nest[j]+1;這是顯然的。

2) arr[k] != arr[j];

這時需要我們稍作分析:因為串3=串4,串1=串2,對應必然有,串5=串6,所以必有,串1=串2=串5=串6。

到目前為止由已知只能推出串1=串6,所以,在此基礎上嘗試擴充套件串,即判斷arr[m]是否等於arr[j]。此時又分情況兩種情況:

1) arr[m = arr[j];nest[i] = nest[m]+1;這是顯然的。

2) arr[m != arr[j];以此方式一直推導下去!

沒錯,遞迴求解是正解!時間複雜度o(m)(m為模式串長度)。

二分演算法的細節問題

尋找乙個數 尋找左側邊界 尋找右側邊界 需不需要帶 號 需不需要 1int binarysearch int nums,int target return 1 上面這段 中,可以發現while內的條件是 而不是 兩者有這樣的區別 符號區間返回條件 left,right left right 1 le...

KMP演算法中的迴圈節問題

迴圈節問題包括 完全迴圈 和 不完全迴圈 對於乙個具有迴圈節並且長為n的字串,其迴圈節長為 n n x t n 1 並且滿足n n n x t n 1 0 這裡nxt 是kmp演算法中的next 陣列,並且是對於本部落格上上上篇給出的kmp模板的方法構造nxt陣列來說的。本篇部落格kmp演算法的講解...

演算法 KMP演算法

kmp演算法主要解決的問題就是在字串 主串 中的模式 pattern 定位問題。記主串為t,模式串為p,則kmp演算法就是返回p在t 現的具體位置,如果沒有出現則返回 1。如果 i 指標指向的字元和 j 指標指向的字元不一致,那麼把 i 右移1位,j 從0位開始,從新開始匹配 如果 i 指標指向的字...