返回

字符串匹配: KMP 算法的部分匹配表

前端

与暴力匹配算法相比,KMP 算法在匹配字符串时具有显著优势。这得益于其对源字符串的遍历中省略了部分循环,从而在某些情况下带来了可观的性能提升。

KMP 算法的部分匹配表解法是其核心。它通过比较模式串的前缀和后缀(概念不再赘述)得到一个部分匹配表数组,从而优化循环。

部分匹配表的构造

设模式串为 P = p1p2...pn,部分匹配表 F[i] 表示以模式串前 i 个字符为后缀的字串中,与自身匹配的最长前缀的长度。

部分匹配表的构造过程如下:

  1. F[0] = 0
  2. 对于 i = 1n
    a. 若 pi = pi-F[i-1],则 F[i] = F[i-1] + 1
    b. 若 pi != pi-F[i-1],则
    i. 若 F[i-1] != 0,则 i = F[i-1],重新执行步骤 a
    ii. 若 F[i-1] = 0,则 F[i] = 0

算法过程

给定源字符串 S 和模式串 P,KMP 算法的匹配过程如下:

  1. i = 0j = 0
  2. j = n,则说明匹配成功,退出循环
  3. i = m,则 j = F[j],并回到步骤 2
  4. Si = Pj,则 i = i + 1j = j + 1,并回到步骤 2
  5. Si != Pj,则 j = F[j],并回到步骤 2

举例

设源字符串 S = abcabdabcabc,模式串 P = abcab,则部分匹配表为:

F[0] = 0
F[1] = 0
F[2] = 1
F[3] = 2
F[4] = 0

匹配过程如下:

  1. i = 0j = 0
  2. S0 = aP0 = a,则 i = 1j = 1
  3. S1 = bP1 = b,则 i = 2j = 2
  4. S2 = cP2 = c,则 i = 3j = 3
  5. S3 = aP3 = a,则 i = 4j = 4
  6. S4 = bP4 = b,则 i = 5j = 5
  7. S5 = dP5 = c,则 j = F[4] = 0
  8. S5 = dP0 = a,则 i = 1j = 1
  9. S6 = aP1 = b,则 j = F[0] = 0
  10. S6 = aP0 = a,则 i = 2j = 1
  11. S7 = bP1 = b,则 i = 3j = 2
  12. S8 = cP2 = c,则 i = 4j = 3
  13. S9 = aP3 = a,则 i = 5j = 4
  14. S10 = bP4 = b,则 i = 6j = 5
  15. S11 = cP5 = c,则匹配成功

因此,KMP 算法在 S 中找到了模式串 P