image.png

    image.png

    1. package com.atguigu.kmp;
    2. import java.util.Arrays;
    3. /**
    4. * KMP算法 --- 字符串匹配问题
    5. *
    6. * @author Dxkstart
    7. * @create 2022-04-13-9:36
    8. */
    9. public class KMP {
    10. public static void main(String[] args) {
    11. String str1 = "BBC ABCDAB ABCDABCDABDE";
    12. String str2 = "ABCDABD";
    13. int[] ints = KMP.kmpNext(str2);
    14. System.out.println(Arrays.toString(ints));
    15. int index = KMP.kmpSearch(str1, str2, ints);
    16. System.out.println("位置:" + index); // 15
    17. }
    18. // 获取到一个字符串的部分匹配值 --> 是给定的子串的部分匹配表
    19. public static int[] kmpNext(String str2) {
    20. // 创建一个next数组保存部分匹配值
    21. int[] next = new int[str2.length()];
    22. // 不管字符串的长度多长,第一位始终是0
    23. next[0] = 0;
    24. // j指向str2 , i指向next[]
    25. for (int i = 1, j = 0; i < str2.length(); i++) {
    26. // 这个while是老师说的kmp核心,但是我把next[i] = j;放到if语句中,照样可以实现
    27. // 原先next[i] = j;是在if外面的,我这样改进暂时没有出现问题
    28. // while (j > 0 && str2.charAt(i) != str2.charAt(j)) {
    29. // j = next[j-1];
    30. // }
    31. if (str2.charAt(i) == str2.charAt(j)) {
    32. j++;
    33. next[i] = j;
    34. }
    35. }
    36. return next;
    37. }
    38. // KMP搜索算法
    39. /**
    40. * @param str1 源字符串
    41. * @param str2 子串
    42. * @param next 子串的部分匹配表
    43. * @return 返回第一个匹配的位置
    44. */
    45. public static int kmpSearch(String str1, String str2, int[] next) {
    46. // 遍历源字符串 i指向str1 , j指向str2
    47. for (int i = 0, j = 0; i < str1.length(); i++) {
    48. if (str1.charAt(i) == str2.charAt(j)) {
    49. j++;
    50. } else {
    51. // 不相等时,i指针不受影响,重新定位j指针
    52. if (j != 0) {
    53. j = next[j - 1];
    54. // 修改
    55. i--;
    56. }
    57. }
    58. // 找到时
    59. if (j == str2.length()) {
    60. return i - j + 1;
    61. }
    62. }
    63. return -1;
    64. }
    65. }