📜  kmp 算法 (1)

📅  最后修改于: 2023-12-03 15:02:31.668000             🧑  作者: Mango

KMP算法

KMP算法是一种字符串匹配算法,可以用于在一个主串中查找一个模式串的出现位置。KMP算法的核心思想是在模式串匹配失败时,尽可能地利用已经匹配成功的前缀信息,快速定位下一次匹配的位置。

实现原理

KMP算法通过跳过已经匹配成功的前缀,来减少匹配次数。在匹配过程中,如果在模式串的某个位置匹配失败,KMP算法会尝试利用已经匹配成功的前缀信息,找到下一个可以尝试匹配的位置。从而减少匹配次数,提高匹配效率。

举个例子:

假设我们要在字符串ABABACABABC中查找ABABC这个模式串,下面是KMP算法的匹配过程:

  1. 首先,模式串的第一个字符A与主串的第一个字符A匹配成功。
  2. 然后,模式串的第二个字符B与主串的第二个字符B匹配成功。
  3. 现在,模式串的第三个字符A与主串的第三个字符A匹配成功。但是,模式串的第四个字符B与主串的第四个字符C不匹配,这个时候,KMP算法会尝试利用已经匹配成功的前缀信息来找到下一个可以尝试匹配的位置。
  4. 在模式串中,由于ABABABC的前缀,而模式串的第一个字符是A,所以下一个可以尝试匹配的位置是模式串中的第二个字符,即B
  5. 在主串中,由于已经匹配成功的前缀为AB,而模式串的第一个字符也是A,所以下一个可以尝试匹配的位置是主串中的第四个字符,即A
  6. 在主串中,模式串的第二个字符B与主串的第五个字符B匹配成功。
  7. 在主串中,模式串的第三个字符A与主串的第六个字符A匹配成功。
  8. 在主串中,模式串的第四个字符B与主串的第七个字符B匹配成功。
  9. 在主串中,模式串的第五个字符C与主串的第八个字符C匹配成功。
  10. 最终,我们在主串中找到了模式串ABABC的出现位置为4。
实现代码

下面是KMP算法的实现代码:

def get_next(p):
    next = [-1] * len(p)
    i, j = 0, -1
    while i < len(p) - 1:
        if j == -1 or p[i] == p[j]:
            i, j = i + 1, j + 1
            next[i] = j
        else:
            j = next[j]
    return next

def kmp(s, p):
    next = get_next(p)
    i, j = 0, 0
    while i < len(s) and j < len(p):
        if j == -1 or s[i] == p[j]:
            i, j = i + 1, j + 1
        else:
            j = next[j]
    if j == len(p):
        return i - j
    else:
        return -1

这段代码中,get_next函数用于计算模式串的next数组,而kmp函数用于在主串中查找模式串的出现位置。具体实现时,我们用i来表示主串中当前尝试匹配的位置,用j来表示模式串中当前尝试匹配的位置。如果当前匹配成功,则让ij分别加1;否则,将j更新为next[j](即尝试利用已经匹配成功的前缀信息来快速定位下一个可以尝试匹配的位置)。匹配成功的条件是整个模式串都已经匹配成功,此时返回模式串在主串中的起始位置,否则返回-1。