串的模式匹配算法概述
串的模式匹配是指在主串(文本串)中查找子串(模式串)出现的位置。这是字符串处理中的基础操作,广泛应用于文本编辑、搜索引擎、生物信息学等领域。常见的模式匹配算法包括朴素匹配算法、KMP算法、Boyer-Moore算法等。
朴素匹配算法(Brute-Force)
朴素匹配算法是最直观的模式匹配方法,通过逐个字符比较主串和模式串来实现。
算法思想
- 从主串的第一个字符开始,与模式串的第一个字符比较。
- 若匹配成功,继续比较后续字符;若匹配失败,主串回溯到起始位置的下一个字符,模式串从头开始。
- 重复上述过程,直到找到匹配的子串或主串遍历完毕。
时间复杂度
- 最坏情况:O(m*n),其中m是主串长度,n是模式串长度。
C语言实现
#include <stdio.h>
#include <string.h>
int bruteForceMatch(char *text, char *pattern) {
int textLen = strlen(text);
int patternLen = strlen(pattern);
for (int i = 0; i <= textLen - patternLen; i++) {
int j;
for (j = 0; j < patternLen; j++) {
if (text[i + j] != pattern[j]) {
break;
}
}
if (j == patternLen) {
return i; // 返回匹配的起始位置
}
}
return -1; // 未找到匹配
}
int main() {
char text[] = "ABABDABACDABABCABAB";
char pattern[] = "ABABCABAB";
int pos = bruteForceMatch(text, pattern);
if (pos != -1) {
printf("Pattern found at index %d\n", pos);
} else {
printf("Pattern not found\n");
}
return 0;
}
举例说明
主串:"ABABDABACDABABCABAB",模式串:"ABABCABAB"。
- 从主串第一个字符开始比较,发现不匹配时,主串指针后移一位,重新比较。
KMP算法(Knuth-Morris-Pratt)
KMP算法通过预处理模式串,利用部分匹配信息避免不必要的回溯,提高匹配效率。
算法思想
- 预处理模式串,生成
next数组,记录模式串中每个位置的最长公共前后缀长度。 - 匹配过程中,若字符不匹配,根据
next数组跳过部分字符,避免主串回溯。
时间复杂度
- 预处理:O(n)
- 匹配:O(m)
- 总体:O(m+n)
C语言实现
#include <stdio.h>
#include <string.h>
void computeLPSArray(char *pattern, int patternLen, int *lps) {
int len = 0;
lps[0] = 0;
int i = 1;
while (i < patternLen) {
if (pattern[i] == pattern[len]) {
len++;
lps[i] = len;
i++;
} else {
if (len != 0) {
len = lps[len - 1];
} else {
lps[i] = 0;
i++;
}
}
}
}
int KMPSearch(char *text, char *pattern) {
int textLen = strlen(text);
int patternLen = strlen(pattern);
int lps[patternLen];
computeLPSArray(pattern, patternLen, lps);
int i = 0, j = 0;
while (i < textLen) {
if (pattern[j] == text[i]) {
i++;
j++;
}
if (j == patternLen) {
return i - j; // 返回匹配的起始位置
} else if (i < textLen && pattern[j] != text[i]) {
if (j != 0) {
j = lps[j - 1];
} else {
i++;
}
}
}
return -1; // 未找到匹配
}
int main() {
char text[] = "ABABDABACDABABCABAB";
char pattern[] = "ABABCABAB";
int pos = KMPSearch(text, pattern);
if (pos != -1) {
printf("Pattern found at index %d\n", pos);
} else {
printf("Pattern not found\n");
}
return 0;
}
举例说明
模式串:"ABABCABAB"的next数组为[0, 0, 1, 2, 0, 1, 2, 3, 4]。
- 当主串和模式串在某个位置不匹配时,根据
next数组跳过部分字符,避免主串回溯。
Boyer-Moore算法
Boyer-Moore算法利用坏字符规则和好后缀规则,跳过大量不必要的比较,适合处理大字符集(如英文文本)。
算法思想
- 坏字符规则:当主串与模式串不匹配时,根据坏字符在模式串中的位置,计算移动距离。
- 好后缀规则:当模式串中存在与好后缀匹配的子串时,计算移动距离。
时间复杂度
- 最坏情况:O(m*n)
- 平均情况:O(m/n)
C语言实现(简化版)
#include <stdio.h>
#include <string.h>
#define NO_OF_CHARS 256
int max(int a, int b) {
return (a > b) ? a : b;
}
void badCharHeuristic(char *pattern, int patternLen, int badchar[NO_OF_CHARS]) {
for (int i = 0; i < NO_OF_CHARS; i++) {
badchar[i] = -1;
}
for (int i = 0; i < patternLen; i++) {
badchar[(int)pattern[i]] = i;
}
}
int BMSearch(char *text, char *pattern) {
int textLen = strlen(text);
int patternLen = strlen(pattern);
int badchar[NO_OF_CHARS];
badCharHeuristic(pattern, patternLen, badchar);
int s = 0;
while (s <= (textLen - patternLen)) {
int j = patternLen - 1;
while (j >= 0 && pattern[j] == text[s + j]) {
j--;
}
if (j < 0) {
return s; // 返回匹配的起始位置
} else {
s += max(1, j - badchar[text[s + j]]);
}
}
return -1; // 未找到匹配
}
int main() {
char text[] = "ABABDABACDABABCABAB";
char pattern[] = "ABABCABAB";
int pos = BMSearch(text, pattern);
if (pos != -1) {
printf("Pattern found at index %d\n", pos);
} else {
printf("Pattern not found\n");
}
return 0;
}
举例说明
主串:"ABABDABACDABABCABAB",模式串:"ABABCABAB"。
- 利用坏字符规则,当不匹配时,跳过多个字符,减少比较次数。
总结
- 朴素匹配算法:简单直观,但效率低,适合短文本和小模式串。
- KMP算法:通过预处理模式串,避免主串回溯,适合重复模式较多的场景。
- Boyer-Moore算法:利用坏字符和好后缀规则,适合大字符集和长模式串。
根据实际需求选择合适的算法,权衡时间复杂度和实现复杂度。

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



