高效的字符串匹配算法
KMP 算法用于在一个字符串(文本)中查找另一个字符串(模式)的所有出现位置。
Next[i] 表示模式串前 i 个字符的最长相等前后缀长度:
void buildNext(const string& p, vector& next) {
int n = p.length();
next.assign(n, 0);
next[0] = -1;
int j = -1;
for (int i = 1; i < n; i++) {
while (j >= 0 && p[i] != p[j + 1])
j = next[j]; // 回溯
if (p[i] == p[j + 1])
j++;
next[i] = j;
}
}
vector KMP(const string& s, const string& p) {
int n = s.length(), m = p.length();
vector next(m), result;
buildNext(p, next);
int j = -1;
for (int i = 0; i < n; i++) {
while (j >= 0 && s[i] != p[j + 1])
j = next[j]; // 利用 Next 数组跳过
if (s[i] == p[j + 1])
j++;
if (j == m - 1) {
result.push_back(i - m + 1); // 匹配成功
j = next[j];
}
}
return result;
}
暴力匹配在失配时,模式串每次只能右移一位。KMP 利用已匹配的信息,直接跳过不可能匹配的位置。
例子:文本串 ABABDABACDABABCABAB,模式串 ABABCABAB