poj 3461 kmp演算法詳細解釋

2021-10-04 13:09:01 字數 1892 閱讀 9736

題目鏈結

kmp演算法已經學過好多次了,但每一次都會忘記,因此打算在這裡藉著這一道模板題記錄下自己對kmp演算法的理解

kmp演算法的核心思想可以理解為:利用目標串自身的資訊,來減少匹配次數提高效率

next陣列的引入

next陣列就是用來幫助利用目標串自身的資訊的。我們這裡定義next陣列表示的是字串的最長公共前字尾長度。那麼對於字串abababac來說,求得其next陣列就如下所示

模式串ab

abab

ac下標0

1234

567next陣列00

1234

50相信通過手工求next陣列大家都能夠理解,難點在於理解**求next陣列。

求解next陣列**分析

void

getnext

(char s,

int next)

}

#我們來分析一下為什麼這樣可以計算next陣列的值。我覺得最關鍵的是:

我們來模擬一下當i等於7的時候,此時k應該為5,我們將s[7]與s[5]進行比較,發現不相等,那麼s[7]接下來該與誰比較呢?

對任何i,進入這步該比較的下標是next[next[i-1]-1],而next[i-1]=k,所以新比較的下標應該是k=next[k-1],如果k為0就不能再往前跳,跳出迴圈進行比較,相等為1,不等為0。

因此s[7]與s[next[4]] 即s[3]比較,

#因為下標到6時,子串有最長公共前字尾ababa,如果s[7]=b=s[k]=s[5],那麼顯然next[7]=6 但是不等。這個最長公共前字尾ababa的最長公共前字尾為3,若s[7]==s[3],則可以保證s[0-4]為這個串的最大公共前字尾。

kmp演算法主要**

for

(int i=

0;i(mainstring[i]

==substring[j]

) j++;if

(j==subl)

}

使用已匹配部分的子串的特徵來減少移動量

主串m為abababcccc,目標串t為ababc

m[4]!=t[4],由於已經匹配的abab的next值為2,下一步直接比較m[4]和t[2]就好了,就相當於t向右移動了兩次。

全部**

#include

#include

#include

#include

#include

using

namespace std;

const

int maxn=

10005

;const

int maxx=

1000005

;int nexts[maxn]

;char mainstring[maxx]

,substring[maxn]

;void

getnext

(char s,

int next)

}int

main()

if(mainstring[i]

==substring[j]

) j++;if

(j==subl)

}printf

("%d\n"

,ans);}

return0;

}

5.後話

其實比較普遍的方法是將next[0]=-1,next[n]定義為0-n-1這部分子串的最大公共字首和。剛開始我是覺得next[0]好理解一些,總體上來說其實演算法的思路都一樣的。

poj3461(KMP演算法) (字串hash)

題意 給出兩個字串,然你判斷第乙個字串在第二個字串中出現的次數。思路 乙個裸的kmp演算法。主要內容在下面 中實現。include include include include include using namespace std int n const int maxn 1e4 5 char ...

kmp演算法鞏固 以poj3461為試驗

本來計畫下一步去搞ac自動機的 忽發現它以kmp為基礎 雖然假期練過,但基本內涵都不太清楚了,都是直接套模板orz 是本次來再補一下 總算把自己的板給寫出來了,真是可喜可賀xd 以下先是kmp的重新理解部分 用parent表示母串,son表示子串 當比較母串和子串時,以abcdefg和bcdf為例 ...

POJ 3461題解(kmp演算法)文字串和子串匹配

poj3461傳送門 特殊的樣例 azaazazaza 輸出 所以next陣列要多一位,0 1 1 2 當模式串比較完之後要指向的是next陣列的最後一位,即開始從第二位字母比較,模擬過程如下 azazaza azazaza aza aza 所以這道題和最基礎的文字串和模式串比較不太一樣,是文字串和...