Knuth-Morris-Pratt (KMP) 算法是一种改进的字符串匹配算法,用于解决在一个主字符串(也称为文本串)中查找一个模式串的位置的问题。相比于朴素的字符串匹配算法,KMP 算法通过利用已匹配部分的信息,避免了在每次匹配失败时都从头开始比较的缺点,从而大大提高了匹配的效率。
KMP算法的核心思想是利用已经部分匹配这个有效信息,当字符串匹配过程中出现字符不匹配时,能知道一部分已经匹配的信息,利用这些信息避免从头开始匹配,从而提高算法效率。
具体来说,KMP算法中定义了一个叫做“部分匹配表”(也称为“失效函数”或“跳转表”)的数据结构,用于存储模式串中各个子串的最长相同前后缀长度。当在文本串中匹配到某个位置时,如果发生不匹配,则根据部分匹配表确定模式串应该回退到的位置,继续匹配。
构建部分匹配表是KMP算法的关键步骤。对于模式串 `P`,其部分匹配表 `lps` 的构建算法如下:
1. `lps[0]` 始终为 0,因为空字符串没有前后缀。
2. 初始化 `len = 0`,用于记录当前最长前后缀的长度。
3. 遍历模式串的每个字符 `P[i]`,其中 `i` 从 1 开始:
- 当 `P[i]` 等于 `P[len]` 时,`len` 增加,意味着最长前后缀长度可以扩展。
- 当 `P[i]` 不等于 `P[len]` 时,如果 `len` 不为 0,则 `len` 更新为 `lps[len-1]`,表示根据上一个位置的部分匹配信息回退;否则 `len` 保持为 0。
- 在每个位置,更新 `lps[i]` 为当前的 `len` 值。
以下是一个C++实现的KMP算法示例,代码如下。
#include <iostream>
#include <vector>
#include <string>using namespace std;// 计算部分匹配表
vector<int> computeLPSArray(const string& pat, int M) {vector<int> lps(M, 0);int len = 0; // length of the previous longest prefix suffixint i = 1;lps[0] = 0; // lps[0] is always 0// the loop calculates lps[i] for i = 1 to M-1while (i <