29.kmp算法

KMP算法

KMP算法是用来做字符串匹配的,他以他的三个发明者命名,其效率非常高。

常见的字符串匹配算法

  • BF(BruteForce)暴力匹配对主串和模式串进行逐个字符匹配,效率很低,每一轮只能将模式串右移一位。
  • BM(Boyer-Moore)算法 核心试想是模式串中不存在的字符一定不匹配,后移
  • KMP算法 核心在于部门匹配表(partial match table),本质也是减少冗余的字符比较

核心代码

获取部分匹配表

  /**
     * PMT中的值是字符串的前缀集合与后缀集合的交集中最长元素的长度
     * 获取字符串的部分匹配表
     */
    public static int[] getPartialMatchTable(String str) {
        int[] table = new int[str.length()];
        // 单个字符 部分匹配表一定是[0]
        table[0] = 0;
        for (int i = 1, j = 0; i < str.length(); i++) {
            // 不匹配
            while (j > 0 && str.charAt(i) != str.charAt(j)) {
                j = table[j - 1];
            }
            if (str.charAt(i) == str.charAt(j)) {
                // 如果匹配 部分匹配值+1
                j++;
            }
            table[i] = j;
        }
        return table;
    }

代码示例

public class KMPMatch {

    public static void main(String[] args) {
        String str1 = "BBC ABCDAB ABCDABCDABDE";
        String str2 = "ABCDABD";
//        System.out.println(Arrays.toString(getPartialMatchTable("ABCDABD")));
        System.out.println(kmpMatch(str1, str2, getPartialMatchTable(str2)));
    }

    /**
     * PMT中的值是字符串的前缀集合与后缀集合的交集中最长元素的长度
     * 获取字符串的部分匹配表
     */
    public static int[] getPartialMatchTable(String str) {
        int[] table = new int[str.length()];
        // 单个字符 部分匹配表一定是[0]
        table[0] = 0;
        for (int i = 1, j = 0; i < str.length(); i++) {
            // 不匹配
            while (j > 0 && str.charAt(i) != str.charAt(j)) {
                j = table[j - 1];
            }
            if (str.charAt(i) == str.charAt(j)) {
                // 如果匹配 部分匹配值+1
                j++;
            }
            table[i] = j;
        }
        return table;
    }

    /**
     *  移动位数 = 已匹配的字符数 - 对应的部分匹配值
     *
     * @param str1
     * @param str2
     * @return
     */
    public static int kmpMatch(String str1, String str2, int[] pmt) {
        for (int i = 0, j = 0; i < str1.length(); i++) {

            while (j > 0 && str1.charAt(i) != str2.charAt(j)) {
                // 利用部分匹配表调整J的位置
                j = pmt[j - 1];
            }
            if (str1.charAt(i) == str2.charAt(j)) {
                j++;
            }
            if (j == str2.length()) {
                return i - j+1;
            }
        }
        return -1;
    }
}

后附上阮一峰老师对部分匹配表的讲解非常的形象!

http://www.ruanyifeng.com/blog/2013/05/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm.html

你可能感兴趣的:(数据结构)