文章目录
前言
字符串匹配算法是计算机科学中非常重要的内容,广泛应用于文本编辑、信息检索、生物信息学等领域。本文将详细介绍几种经典的字符串匹配算法,并给出对应的C++实现代码,包括:
- 朴素字符串匹配算法(Naive)
- KMP算法(Knuth-Morris-Pratt)
- BM算法(Boyer-Moore)
通过这些算法的学习,读者不仅能理解字符串匹配的基本原理,还能掌握优化匹配效率的实用技巧。
一、字符串匹配算法简介
字符串匹配的任务是判断一个模式串 pattern 是否出现在主串 text 中,如果出现,返回匹配的位置,否则返回未找到。
最简单的方式是朴素匹配,暴力尝试所有可能的起点,时间复杂度为 O(mn),其中 m 是模式串长度,n 是主串长度。效率较低。
为提升效率,研究者设计了 KMP、BM 等算法,通过利用匹配失败时的信息避免重复比较,实现线性甚至接近线性的时间复杂度。
二、朴素字符串匹配算法
1. 算法原理
从主串的每个位置开始尝试匹配模式串,如果某字符不匹配,则移动主串起点向后一个位置,继续尝试。
2. 代码示例
#include <iostream>
#include <string>
int naiveSearch(const std::string& text, const std::string& pattern) {
int n = text.size();
int m = pattern.size();
for (int i = 0; i <= n - m; i++) {
int j = 0;
while (j < m && text[i + j] == pattern[j]) {
j++;
}
if (j == m) {
return i; // 找到匹配,返回位置
}
}
return -1; // 未找到匹配
}
int main() {
std::string text = "hello world";
std::string pattern = "world";
int pos = naiveSearch(text, pattern);
if (pos != -1) {
std::cout << "匹配成功,位置:" << pos << std::endl;
} else {
std::cout << "未找到匹配" << std::endl;
}
return 0;
}
三、KMP算法(Knuth-Morris-Pratt)
1. 算法原理
KMP算法核心是利用已经匹配过的部分信息,避免回溯主串的指针。其关键在于计算模式串的“最长前缀后缀表”(next数组),表示当前位置之前子串的最大相等前后缀长度。
匹配失败时,根据next数组移动模式串位置,达到时间复杂度O(m + n)。
2. 计算next数组代码
#include <vector>
#include <string>
std::vector<int> computeNext(const std::string& pattern) {
int m = pattern.size();
std::vector<int> next(m, 0);
int j = 0; // 前缀末尾指针
for (int i = 1; i < m; i++) {
while (j > 0 && pattern[i] != pattern[j]) {
j = next[j - 1]; // 回溯
}
if (pattern[i] == pattern[j]) {
j++;
}
next[i] = j;
}
return next;
}
3. KMP主匹配函数
int kmpSearch(const std::string& text, const std::string& pattern) {
if (pattern.empty()) return 0;
int n = text.size();
int m = pattern.size();
std::vector<int> next = computeNext(pattern);
int j = 0; // 模式串指针
for (int i = 0; i < n; i++) {
while (j > 0 && text[i] != pattern[j]) {
j = next[j - 1]; // 根据next数组回溯模式串指针
}
if (text[i] == pattern[j]) {
j++;
}
if (j == m) {
return i - m + 1; // 匹配成功,返回位置
}
}
return -1; // 未找到匹配
}
4. 测试示例
int main() {
std::string text = "abxabcabcaby";
std::string pattern = "abcaby";
int pos = kmpSearch(text, pattern);
if (pos != -1) {
std::cout << "KMP匹配成功,位置:" << pos << std::endl;
} else {
std::cout << "未找到匹配" << std::endl;
}
return 0;
}
四、Boyer-Moore算法简介
BM算法采用“坏字符规则”和“好后缀规则”,跳跃式移动模式串,通常在实际文本中表现优于KMP。实现较复杂,此处只简单介绍。
- 坏字符规则:匹配失败时,将模式串向右滑动,使得坏字符对齐模式串中该字符的最后一次出现。
- 好后缀规则:匹配失败时,根据已经匹配的后缀,在模式串中找到另一个相同的后缀进行对齐。
BM算法适合模式串较长,文本较大场景。
总结
本文介绍了三种字符串匹配算法的基本原理和C++实现:
- 朴素算法,简单直接,但效率低。
- KMP算法,利用next数组实现高效匹配,时间复杂度O(m+n)。
- Boyer-Moore算法,基于启发式跳跃,实际效率很高。

被折叠的 条评论
为什么被折叠?



