目录
一、基本概念
KMP算法(Knuth-Morris-Pratt Algorithm)是一种高效的字符串匹配算法,用于在一个文本串(text)中查找一个模式串(pattern)的出现位置。与朴素的字符串匹配算法相比,KMP算法能够有效地避免不必要的字符比较,从而提高匹配效率。
二、功能
KMP算法的主要功能是:
-
在一个文本串中查找模式串的出现位置。
-
返回模式串在文本串中所有出现位置的起始索引。
三、深度剖析
1. 算法原理
KMP算法的核心思想是利用模式串自身的重复结构来减少不必要的字符比较。它通过构建一个前缀表(也称为“next”表),记录模式串中每个位置的“最长 proper 前缀”的长度。
-
Proper 前缀: 指一个字符串的除自身以外的所有前缀子串。
-
最长 Proper 前缀: 指所有 Proper 前缀中,也是模式串的后缀的最长子串。
例如,对于模式串 "ABCDABD",其前缀表为:
i | 0 1 2 3 4 5 6
-------------------------
next[i] | -1 0 0 0 1 2 0
2. 算法流程
KMP算法的流程如下:
-
构建前缀表: 根据模式串构建前缀表。
-
匹配过程: 使用两个指针
i
和j
分别指向文本串和模式串的当前位置。-
如果
text[i]
和pattern[j]
相等,则i
和j
都向后移动一位。 -
如果
text[i]
和pattern[j]
不相等,则使用前缀表next[j]
来确定j
指针应该移动到哪个位置,以避免不必要的字符比较。
-
3. 前缀表构建
构建前缀表的思路是:
-
从第二个字符开始,依次遍历模式串的每个字符。
-
对于每个字符
pattern[i]
,找到其最长 proper 前缀,并记录其长度到next[i]
中。 -
找到最长 proper 前缀的方法是:
-
从
i - 1
位置开始,向前遍历pattern
,直到找到一个位置k
,满足pattern[k]
等于pattern[i]
。 -
如果找到了这样的
k
,则next[i]
的值为k + 1
。 -
如果没有找到这样的
k
,则next[i]
的值为 0。
-
4. 代码实现
#include <stdio.h>
#include <string.h>
void computeLPSArray(char* pattern, int M, int* lps)
{
int length = 0;
lps[0] = 0;
int i = 1;
while (i < M)
{
if (pattern[i] == pattern[length])
{
length++;
lps[i] = length;
i++;
}
else
{
if (length != 0)
{
length = lps[length - 1];
}
else
{
lps[i] = 0;
i++;
}
}
}
}
void KMPSearch(char* text, char* pattern)
{
int N = strlen(text);
int M = strlen(pattern);
int lps[M];
computeLPSArray(pattern, M, lps);
int i = 0; // 文本串指针
int j = 0; // 模式串指针
while (i < N)
{
if (text[i] == pattern[j])
{
i++;
j++;
}
if (j == M)
{
printf("模式串出现于索引 %d\n", i - j);
j = lps[j - 1];
}
else if (i < N && text[i] != pattern[j])
{
if (j != 0)
{
j = lps[j - 1];
}
else
{
i++;
}
}
}
}
int main()
{
char text[] = "ABABDABACDABABCABAB";
char pattern[] = "ABABCABAB";
KMPSearch(text, pattern);
return 0;
}
五、算法复杂度
-
时间复杂度: O(N),其中 N 是文本串的长度。KMP算法能够有效地避免不必要的字符比较,因此其时间复杂度与文本串的长度成线性关系。
-
空间复杂度: O(M),其中 M 是模式串的长度。KMP算法需要使用一个大小为 M 的前缀表。
六、应用场景
KMP算法广泛应用于各种字符串匹配场景,例如:
-
文本编辑器中的查找功能。
-
网络安全中的入侵检测系统。
-
生物信息学中的基因序列匹配。
-
数据压缩算法中的模式匹配。
七、总结
KMP算法是一种高效的字符串匹配算法,能够有效地减少不必要的字符比较,提高匹配效率。它在各种字符串处理场景中都有广泛的应用,是计算机科学中重要的算法之一。