

package com.atguigu.kmp;import java.util.Arrays;/** * KMP算法 --- 字符串匹配问题 * * @author Dxkstart * @create 2022-04-13-9:36 */public class KMP { public static void main(String[] args) { String str1 = "BBC ABCDAB ABCDABCDABDE"; String str2 = "ABCDABD"; int[] ints = KMP.kmpNext(str2); System.out.println(Arrays.toString(ints)); int index = KMP.kmpSearch(str1, str2, ints); System.out.println("位置:" + index); // 15 } // 获取到一个字符串的部分匹配值 --> 是给定的子串的部分匹配表 public static int[] kmpNext(String str2) { // 创建一个next数组保存部分匹配值 int[] next = new int[str2.length()]; // 不管字符串的长度多长,第一位始终是0 next[0] = 0; // j指向str2 , i指向next[] for (int i = 1, j = 0; i < str2.length(); i++) { // 这个while是老师说的kmp核心,但是我把next[i] = j;放到if语句中,照样可以实现 // 原先next[i] = j;是在if外面的,我这样改进暂时没有出现问题// while (j > 0 && str2.charAt(i) != str2.charAt(j)) {// j = next[j-1];// } if (str2.charAt(i) == str2.charAt(j)) { j++; next[i] = j; } } return next; } // KMP搜索算法 /** * @param str1 源字符串 * @param str2 子串 * @param next 子串的部分匹配表 * @return 返回第一个匹配的位置 */ public static int kmpSearch(String str1, String str2, int[] next) { // 遍历源字符串 i指向str1 , j指向str2 for (int i = 0, j = 0; i < str1.length(); i++) { if (str1.charAt(i) == str2.charAt(j)) { j++; } else { // 不相等时,i指针不受影响,重新定位j指针 if (j != 0) { j = next[j - 1]; // 修改 i--; } } // 找到时 if (j == str2.length()) { return i - j + 1; } } return -1; }}