这里写自定义目录标题
- 介绍
- KMP算法的核心思想
- KMP算法的步骤
- 例题
- 问题分析
- 图解
- 代码
- 输出结果
介绍
- KMP(Knuth-Morris-Pratt)算法是一种用于在一个文本串(text)中查找一个模式串(pattern)的高效字符串匹配算法。相比暴力破解法,KMP算法利用了模式串内部的信息,在匹配过程中避免重复比较已经比较过的字符,从而提高了匹配效率。
KMP算法的核心思想
- 构建最长前缀后缀匹配表(lps数组):在KMP算法中,首先需要构建模式串的最长前缀后缀匹配表(也称为部分匹配表),通过这个表可以指导模式串在匹配过程中的移动。
- 匹配过程:在匹配过程中,通过利用最长前缀后缀匹配表,可以避免在文本串中不必要的回溯,从而提高匹配效率。
KMP算法的步骤
- 构建最长前缀后缀匹配表(lps数组):根据模式串的字符构建一个最长前缀后缀匹配表,表中每个位置记录着当前位置之前的最长相等前缀后缀的长度。
- 在匹配过程中,根据文本串和模式串的字符进行比较,利用最长前缀后缀匹配表指导模式串的移动。
- 当模式串完全匹配时,返回匹配的起始位置;否则,根据匹配失败时的情况对模式串进行移动,继续匹配。
KMP算法的时间复杂度为O(m+n),其中m为文本串的长度,n为模式串的长度。由于KMP算法充分利用了模式串内部的信息,在实际应用中具有较高的效率。
例题
问题分析
-
- 有一个字符串strl=“BBC ABCDAB ABCDABCDABDE”,和一个子串str2=“ABCDABD”
-
- 现在要判断 strl是否含有str2,如果存在,就返回第一次出现的位置,如果没有,则返回-1
-
- 要求:使用KMP算法完成判断,不能使用简单的暴力匹配算法
图解
代码
import java.util.Arrays;
public class kpm2 {
public static void main(String[] args) {
String s1 = "硅谷 尚硅谷你尚硅谷 尚硅谷你上硅谷你好啊";
String s2 = "尚硅谷你尚硅";
System.out.println(Arrays.toString(kpmNext(s2)));
System.out.println(kpm(s1,s2,kpmNext(s2)));
}
private static int kpm(String s1 ,String s2 ,int[] arr){
for (int i = 0 , j = 0; i < s1.length(); i++) {
//移动s2,字符串的位置从而达到降循环次数
if (j > 0 && s1.charAt(i) != s2.charAt(j)){
j = arr[j - 1];
}
//要是相同就j++; 让判断的s2字符串向后移动
if (s1.charAt(i) == s2.charAt(j)){
j++;
}
if (j == s2.length()){//找到
return i - j + 1;
}
}
//没有找到
return -1;
}
//获得到一个字符串(字串)的部分匹配值表
private static int[] kpmNext(String s2){
int[] next = new int[s2.length()];
next[0] = 0;
for (int i = 1 , j = 0; i < s2.length() ; i++) {
//kpm 核心代码 ,得出特殊情况下的j的值
if (j > 0 && s2.charAt(i) != s2.charAt(j)){
j = next[j - 1];
}
//只要相同就+1
if (s2.charAt(i) == s2.charAt(j)){
j ++;
}
//把j的数字放到next中
next[i] = j;
}
return next;
}
}
输出结果
[0, 0, 0, 0, 1, 2]
3