KMP 算法 C 语言实现详解:深入理解字符串模式匹配
2023-10-02 15:31:41
KMP 算法 C 语言实现详解
摘要
本文旨在深入剖析 KMP 算法的 C 语言实现,揭示其在模式匹配中的强大功效。通过深入理解算法的原理、实现细节和应用实例,读者将掌握 KMP 算法的精髓。
引言
KMP 算法(又称 Knuth-Morris-Pratt 算法)是一种高效的字符串模式匹配算法,广泛用于文本处理、生物信息学和其他领域。它由 Donald Knuth、James Morris 和 Vaughan Pratt 于 1977 年提出,以其卓越的性能和广泛的应用著称。
算法原理
KMP 算法的核心思想在于利用部分匹配表(PMT)来避免冗余比较。PMT 是一个长度为模式串长度的数组,其中每个元素表示模式串中对应字符的失效函数值。失效函数值定义为模式串中该字符及其前缀串的最大匹配长度。
在匹配过程中,算法使用 PMT 优化匹配步骤。当比较模式串的当前字符与目标串的当前字符不匹配时,算法不会从头开始比较,而是根据 PMT 跳转到模式串中匹配位置最靠前的前缀串的下一个字符,从而节省比较次数。
C 语言实现
以下是用 C 语言实现的 KMP 算法:
#include <stdio.h>
#include <string.h>
// 计算失配函数
void computeLPSArray(char *pat, int M, int *lps) {
int len = 0;
lps[0] = 0;
i = 1;
while (i < M) {
if (pat[i] == pat[len]) {
len++;
lps[i] = len;
i++;
} else {
if (len != 0) {
len = lps[len - 1];
} else {
lps[i] = 0;
i++;
}
}
}
}
// KMP 算法
void KMP(char *txt, char *pat) {
int M = strlen(pat);
int N = strlen(txt);
int lps[M];
// 计算失配函数
computeLPSArray(pat, M, lps);
int i = 0; // txt 指针
int j = 0; // pat 指针
while (i < N) {
if (pat[j] == txt[i]) {
j++;
i++;
if (j == M) {
printf("模式串在目标串中出现的位置:%d\n", i - j);
j = lps[j - 1];
}
} else {
if (j != 0) {
j = lps[j - 1];
} else {
i++;
}
}
}
}
int main() {
char txt[] = "ABABDABACDABABCABAB";
char pat[] = "ABABCABAB";
KMP(txt, pat);
return 0;
}
应用实例
以下是一个应用 KMP 算法的实例,展示如何在一个目标串中查找一个模式串:
目标串: ABABDABACDABABCABAB
模式串: ABABCABAB
匹配结果:
模式串在目标串中出现的位置:10
性能分析
KMP 算法的时间复杂度为 O(m + n),其中 m 和 n 分别是模式串和目标串的长度。与朴素算法 O(mn) 的时间复杂度相比,KMP 算法具有显著的优势,尤其是在模式串较长的情况下。
优点和局限性
优点:
- 高效:与朴素算法相比,时间复杂度更低。
- 鲁棒性:在各种应用场景中表现出色。
- 简单易懂:算法原理清晰,易于理解和实现。
局限性:
- 依赖模式串:算法的性能受模式串长度的影响。
- 存储开销:需要额外存储空间来计算 PMT。
总结
KMP 算法是一种高效、鲁棒且易于理解的字符串模式匹配算法。其 C 语言实现充分展现了算法的强大功能,在文本处理和数据科学等领域具有广泛的应用。掌握 KMP 算法是程序员必备的技能,它可以大大提高字符串处理任务的效率。