Java十大经典算法—KMP

发布时间:2024年01月12日

字符串匹配问题:

1.暴力匹配

public class ViolenceMatch {
    public static void main(String[] args) {
        String str1 = "硅硅谷 尚硅谷你尚硅 尚硅谷你尚硅谷你尚硅你好";
        String str2 = "尚硅谷你尚硅你好";
        int index = violenceMatch(str1, str2);
        System.out.println("index=" + index);
    }

    //暴力匹配算法
    public static int violenceMatch(String str1, String str2) {
        char[] s1 = str1.toCharArray();
        char[] s2 = str2.toCharArray();
        int s1Len =s1.length;
        int s2Len =s2.length;

        int i = 0;//i索引指向s1
        int j = 0;//j索引指向s2
        while (i < s1Len && j < s2Len) {
            if (s1[i] == s2[j]) {
                i++;
                j++;
            }else {
                //如果匹配指令失败,令i=i-(j-1)【向后移一位】,j=0
                i=i-(j-1);
                j=0;
            }
        }
        if (j == s2Len) {
            return i-j;
        }else {
            return -1;
        }

    }
}

2.KMP算法?

概念

Knuth-Morris-Pratt 字符串查找算法,简称为 “KMP 算法”,常用于在一个文本串 S 内查找一个模式串 P 的出现位置,这个算法由 Donald Knuth、Vaughan Pratt、James H. Morris 三人于 1977 年联合发表,故取这 3 人的姓氏命名此算法.

KMP 方法算法就利用之前判断过信息,通过一个 next 数组,保存模式串中前后最长公共子序列的长度,每次回溯时,通过 next 数组找到,前面匹配过的位置,省去了大量的计算时间

key:next数组、KMP搜索🔍

流程与关键图解

流程图解
关键图解——匹配表
代码(核心点待理解)
import java.util.Arrays;

public class KMP {
    public static void main(String[] args) {
        int[]next = kmpNext("ABCDABD");
        System.out.println("next"+ Arrays.toString(next));

    }

    /**
     *
     * @param str1 源字符串
     * @param str2 子串
     * @param next 部分匹配值表
     * @return 如果是-1 就是没有匹配到,否则返回第一个匹配的位置
     */
    public static int kmpSearch(String str1,String str2,int[]next){
        //遍历
        for (int i = 0,j=0; i < str1.length(); i++) {
            //需要处理 str1.charAt(i) != str2.charAt(j), 去调整 j 的大小
            //KMP 算法核心点, 可以验证..
            while(j>0&&str1.charAt(i)!=str2.charAt(j)){
                j=next[j-1];
            }
            if (str1.charAt(i)==str2.charAt(j)){
                j++;
            }
            if (j==str2.length()){
                return i-j+1;
            }
        }
        return -1;
    }

    //获取字符串的部分匹配值表
    public static int[] kmpNext(String dest){
        //创建一个next数组保存部分匹配值
        int[]next=new int[dest.length()];
        next[0]=0;//如果匹配字符串长度位1,部分匹配值就为0
        for (int i = 1,j=0; i <dest.length(); i++) {
            //当 dest.charAt(i) != dest.charAt(j) ,我们需要从 next[j-1]获取新的 j
            //直到我们发现 有 dest.charAt(i) == dest.charAt(j)成立才退出
            //这时 kmp 算法的核心点
            while (j>0&&dest.charAt(i)!=dest.charAt(j)){
                j=next[j-1];//???
            }
            //当 dest.charAt(i) == dest.charAt(j) 满足时,部分匹配值就是+1
            if (dest.charAt(i)==dest.charAt(j)){
                j++;
            }
            next[i]=j;
        }
        return next;
    }

}

文章来源:https://blog.csdn.net/m0_55049655/article/details/135562476
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。