Live2D

KMP算法

KMP算法最关键的一步在于寻找最长公共前缀后缀长度

而回溯的长度 = 已匹配字符数 - 失配字符前一个字符的最长公共前缀后缀长度

 

  • 寻找前缀后缀最长公共元素长度:
  • 如果给定的模式串为“abab”,那么它的各个子串的前缀后缀的公共元素的最大长度数组a为0 0 1 2:
  • 相应的回溯数组next为a向右平移一位,且b[0]=-1; (可选)
  •  可以把《最大长度表》看做是next 数组的雏形,甚至就把它当做next 数组也是可以的,区别不过是怎么用的问题。

     

模式串中在j 处的字符跟文本串在i 处的字符匹配失配时,下一步用next [j] 处的字符(或a[j-1]处字符)继续跟文本串i 处的字符匹配,相当于模式串向右移动 j - next[j] 位。

这里可以这样理解:

 已匹配字符长度:3  失配字符j=3处前一位字符A的最大共同前后缀长度为1

 

 

大白话说就是,你在哪里匹配失败了,你就得尽可能多地移动你的模式字符串,移动多少字符数的依据主要就是看

失配字符前一个字符的最长后缀长度。

直接上代码:

 

 

import java.util.Arrays;

public class kmp {
    public static int[] next;

    public static void main(String[] args) {
        String str1 = "ABCABD";
        getNext(str1);
        System.out.println(Arrays.toString(next)) ;
        int i = kmpSearch("ABABCABD", "ABCABD");
        System.out.println(i) ;
    }
    public static void getNext(String str1){

        char[] s1 = str1.toCharArray();
        int length = s1.length;
        next = new int[length];
        next[0] = 0;
        for(int i = 1,j = 0; i < length; i++){
            while(j > 0 && s1[i] != s1[j]){
                j = next[j-1];
            }
            if(s1[i] == s1[j]){
                j++;
            }
            next[i] = j;
        }
    }
    public static int kmpSearch(String str1, String str2){
        char[] s1 = str1.toCharArray();
        char[] s2 = str2.toCharArray();
        for (int i = 0, j = 0; i < str1.length(); i++){
            while (j > 0 && s1[i] != s2[j]){
                j = next[j-1];
            }
            if(s1[i] == s2[j]){
                j++;
            }
            if( j == str2.length()){
                return i - j + 1;
            }
        }
        return -1;
    }
}

设模式串长度为m,待匹配字符串长度为n

时间复杂度为o(m)+o(n)

如有错误,麻烦在评论区指出

posted @ 2020-11-17 22:43  eminemrapgod  阅读(81)  评论(0编辑  收藏  举报