題目鏈結
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 所以這道題和最基礎的文字串和模式串比較不太一樣,是文字串和...