具体的匹配过程如下:
KMP算法的时间复杂度为O(m +
n),其中m为模式串的长度,n为文本串的长度。相比于朴素的字符串匹配算法,KMP算法通过利用已匹配的前缀信息,避免了一些不必要的比较,从而提高了匹配的效率。
public class Kmp {
// 构建next数组
private int[] buildNext(String pattern) {
int[] next = new int[pattern.length()]; // next数组,用于记录最长公共前缀和后缀的长度
int i = 0; // pattern的索引
int j = -1; // next数组的值
next[0] = -1; // 第一个字符的next值为-1
while (i < pattern.length() - 1) {
if (j == -1 || pattern.charAt(i) == pattern.charAt(j)) {
i++;
j++;
next[i] = j;
} else {
j = next[j];
}
}
return next;
}
// KMP算法匹配
public int kmpMatch(String text, String pattern) {
int[] next = buildNext(pattern);
System.out.println("next数组:");
for(int i=0;i<next.length;i++){
if(i==next.length-1){
System.out.print(next[i]+"\n");
}else{
System.out.print(next[i]);
}
}
int i = 0; // text的索引
int j = 0; // pattern的索引
while (i < text.length() && j < pattern.length()) {
if (j == -1 || text.charAt(i) == pattern.charAt(j)) {
i++;
j++;
} else {
j = next[j];
}
}
if (j == pattern.length()) {
return i - j; // 返回匹配的起始位置
} else {
return -1; // 没有匹配的子串
}
}
// 测试
public static void main(String[] args) {
String text = "abbabbababaaababaaababab";//文本串
String pattern = "ababaaababaa";//模式串
Kmp kmp=new Kmp();
int index = kmp.kmpMatch(text, pattern);
if (index != -1) {
System.out.println("在位置 " + index + " 处找到匹配的子串");
} else {
System.out.println("未找到匹配的子串");
}
}
}
简单地说一下next数组吧:
1、先求模式串每个子串的最长公共前后缀
2、然后看题目要求(有时候你得两种情况都抽一眼)
(1)下标从0开始:将上面求的数组整体右移一位(第一位补-1)
(2)下标从1开始:将第一种情况求得的数组加1