KMP算法的核心原理及其在字符串匹配中的应用
KMP算法简介
Knuth-Morris-Pratt(KMP)字符串搜索算法是一种高效的字符串搜索(或模式匹配)算法,由Donald Knuth、Vaughan Pratt和James H. Morris共同发明。
KMP算法核心原理
KMP算法的核心在于预处理模式字符串,生成一个部分匹配表(也称为"前缀"表或"部分失败函数"),该表用于在不匹配的情况下跳过尽可能多的字符。
部分匹配表
部分匹配表pi
定义为:对于模式字符串p[1..m]
,pi
是最大的j
(0 ≤ j ≤ i),使得p[1..j]
是p[1..i]
的前缀。
KMP算法步骤
- 预处理模式字符串,生成部分匹配表。
- 将模式字符串与文本字符串对齐的第一个字符。
- 从模式字符串的第一个字符开始,逐个字符与文本字符串比较。
- 如果字符匹配,继续比较下一个字符。
- 如果字符不匹配,根据部分匹配表确定模式字符串应该移动到哪个位置重新与文本对齐。
KMP算法实现
以下是KMP算法的Java实现示例:
package cn.juwatech.algorithm.kmp;
public class KMPSearch {
// 生成部分匹配表
private static int[] computePartialMatchTable(String pattern) {
int[] pi = new int[pattern.length()];
int j = 0, k = -1;
for (int i = -1; j < pattern.length(); i = pi[j], j++) {
while (k >= 0 && pattern.charAt(j) != pattern.charAt(k)) {
k = pi[k];
}
if (pattern.charAt(j) == pattern.charAt(k)) {
k++;
}
pi[j] = k;
}
return pi;
}
// KMP搜索算法
public static int[] search(String text, String pattern) {
int[] pi = computePartialMatchTable(pattern);
int m = pattern.length();
int n = text.length();
int[] shifts = new int[n + 1];
int i = 0, j = 0;
while (i < n) {
if (pattern.charAt(j) == text.charAt(i)) {
j++;
i++;
}
if (j == m) {
shifts[i - j] = j;
j = pi[j - 1];
}
// 处理不匹配的情况
else if (i < n && pattern.charAt(j) != text.charAt(i)) {
if (j != 0) {
j = pi[j - 1];
} else {
i++;
}
}
}
return shifts;
}
public static void main(String[] args) {
String text = "ABC ABCDAB ABCDABCDABDE";
String pattern = "ABCDABD";
int[] shifts = search(text, pattern);
System.out.println("Pattern found at shifts: ");
for (int shift : shifts) {
if (shift != 0) {
System.out.println(shift);
}
}
}
}
KMP算法的应用
KMP算法广泛应用于文本编辑器、搜索引擎、生物信息学等领域,用于快速准确地进行字符串匹配。
结语
KMP算法是一种强大的字符串搜索工具,通过预处理模式字符串来优化搜索过程。本文通过介绍KMP算法的原理和Java实现,希望读者能够理解并掌握这种高效的字符串匹配方法。在实际编程中,KMP算法可以显著提高字符串处理的效率。