KMP算法的两种理解

目录

  • 失配数组观点下的KMP算法
  • 基于Border理论的KMP算法

基于Border理论的KMP算法

Border定义

对于一个长度为 n n n的字符串 S S S(下标从 1 1 1开始),若 1 ≤ k < n 1\leq k< n 1k<n,且 S [ 1.. k ] = S [ n − k + 1.. n ] S[1..k]=S[n-k+1..n] S[1..k]=S[nk+1..n],则称 S [ 1.. k ] S[1..k] S[1..k] S S S的一个 b o r d e r border border
注: S [ l . . r ] S[l..r] S[l..r]表示下标从 l l l r r r S S S的子串;例如:对于 S = S= S=" a b c a c a b a b c a b abcacababcab abcacababcab", S [ 2..5 ] = S[2..5]= S[2..5]=" b c a c bcac bcac"。

Border的性质

  • S S S的一个 b o r d e r border border b o r d e r border border一定也是 S S S b o r d e r border border
    证明:
    S [ 1.. k ] S[1..k] S[1..k] S S S的一个 b o r d e r border border,则有 S [ 1.. k ] = S [ n − k + 1.. n ] S[1..k]=S[n-k+1..n] S[1..k]=S[nk+1..n]
    S [ 1.. k ′ ] S[1..k'] S[1..k] S [ 1.. k ] S[1..k] S[1..k]的一个 b o r d e r border border,则有 S [ 1.. k ′ ] = S [ k − k ′ + 1.. k ] S[1..k']=S[k-k'+1..k] S[1..k]=S[kk+1..k]
    S [ 1.. k ] S[1..k] S[1..k] S S S的一个 b o r d e r border border,所以 S [ k − k ′ + 1.. k ] = S [ n − k ′ + 1.. n ] S[k-k'+1..k]=S[n-k'+1..n] S[kk+1..k]=S[nk+1..n],从而有 S [ 1.. k ′ ] = S [ k − k ′ + 1.. k ] = S [ n − k ′ + 1.. n ] S[1..k']=S[k-k'+1..k]=S[n-k'+1..n] S[1..k]=S[kk+1..k]=S[nk+1..n],即 S [ 1.. k ′ ] S[1..k'] S[1..k]也是 S S S的一个 b o r d e r border border,证毕。
  • n x t [ i ] nxt[i] nxt[i]表示 S S S的前缀 S [ 1.. i ] S[1..i] S[1..i]的最长 b o r d e r border border的长度,则 S S S的所有 b o r d e r border border长度可以表示为: n x t [ n ] , n x t [ n x t [ n ] ] , n x t [ n x t [ n x t [ n ] ] ] . . . nxt[n],nxt[nxt[n]],nxt[nxt[nxt[n]]]... nxt[n],nxt[nxt[n]],nxt[nxt[nxt[n]]]...

KMP算法流程

KMP算法可以在 O ( n ) O(n) O(n)时间内求出 n x t nxt nxt数组,从而获得字符串 S S S的所有 b o r d e r border border的信息,并根据 b o r d e r border border的信息进行文本串与模式串的匹配

计算 n x t nxt nxt数组

  • 首先, n x t [ 1 ] = 0 nxt[1]=0 nxt[1]=0;现在考虑在已知 n x t [ 1.. i − 1 ] nxt[1..i-1] nxt[1..i1]的情况下求解 n x t [ i ] nxt[i] nxt[i]
  • 根据 b o r d e r border border的定义可知,如果 S [ 1.. j ] S[1..j] S[1..j] S S S的一个 b o r d e r border border,那么 S [ 1.. j − 1 ] S[1..j-1] S[1..j1]一定是 S [ 1.. n − 1 ] S[1..n-1] S[1..n1]的一个 b o r d e r border border
  • 因此,从大到小检索 S [ 1.. i − 1 ] S[1..i-1] S[1..i1]的所有 b o r d e r border border的长度 j j j,如果 S [ j + 1 ] = S [ i ] S[j+1]=S[i] S[j+1]=S[i],那么 j + 1 j+1 j+1就是 S [ 1.. i ] S[1..i] S[1..i]的最长 b o r d e r border border的长度
memset(nxt, 0, sizeof nxt);
for (int i = 2, j = 0; i <= n; ++i) {
  while (j != 0 && s[j+1] != s[i]) j = nxt[j];
  if (s[j+1] == s[i]) nxt[i] = j, ++j;
}

你可能感兴趣的:(字符串——KMP)