int kmp(const std::string& text, const std::string& pattern)
{
if (pattern.length() == 0)
return -1;
// 建立next数组 (直接以前缀表表示)
std::vector<int> next(pattern.length());
{
next[0] = 0;
int i = 1; // 用于遍历的指针
int j = 0; // 最长相等前缀的下一位指针 (也表示当前最长相等前后缀的长度)
while (i < pattern.length()) {
if (pattern[i] == pattern[j]) { // 字符相等, 可以组成新的更长前后缀, 递推加一
j++;
next[i++] = j;
} else { // 出现不相等字符
/**
* 既然无法组成更长的前后缀,那么则从已经找到的最长相等前后缀prefix里,
* 找prefix本身的prefix,也就是改变最长相等前缀的下一位指针j,尝试看能否与当前字符组成新的前后缀
**/
if (j > 0)
j = next[j - 1];
/**
* 说明当前遍历的字符与首个字符就无法构成最长相等前后缀,则直接更新为0
**/
else
next[i++] = 0;
}
}
}
// 模式匹配
int i = 0;
int j = 0;
while (i < text.length()) {
if (text[i] == pattern[j]) { // 匹配, 主串和模式串指针继续前进
i++;
j++;
} else if (j > 0) { // pattern中间字符失配, 主串指针不回溯, 模式串指针根据next数组更新
j = next[j - 1];
} else { // pattern首个字符失配, 主串指针继续前进
i++;
}
if (j == pattern.length())
return i - j;
}
return -1;
}
KMP算法
最新推荐文章于 2025-06-17 14:41:04 发布