[KMP] Store intermediate changes through the longest suffix---applicable to Chinese character matching, etc.

Supplemented that the previous version of KMP can only be compatible with characters and numbers

There are comments in the code - please point out the wrong place and learn together

package com.test.autimatic;

/**
 * KMP算法
 * @author 25338
 * @version 1.0
 * @date 2021/12/22 21:37
 */
public class GpKmp {
    
    

    public static void main(String[] args) {
    
    
        System.out.println(kmp("abbabbabab","abbaba"));
    }

    /**
     * 注:最长前缀和最长后缀匹配字符abbabb -》 最长前缀3-abb  === 最长后缀3-abb
     * ①.以aabsaasjbk为例
     * ②.定义最长前后缀长度数组 int【】 kmp
     * ③.kmp[0] =-1;kmp[1] = 0;固定
     * ④.其他以注中求值
     * ⑤.
     */
    public final static int kmp(String source,String target){
    
    
        if(source == null || target == null || source.length() < target.length()){
    
    
            return -1;
        }
        //记录source下标位置和target下标位置
        int s = 0;
        int t = 0;
        //获取target中每个字符对应的最长前后缀相等的长度
        int[] arrayKmp = getArrayKmp(target);
        //循环遍历source
        for (; s < source.length() && t < target.length();) {
    
    
            String sStr = source.substring(s, s + 1);
            String tStr = target.substring(t, t + 1);
            //如果相等则继续
            if(sStr.equals(tStr)){
    
    
                t++;s++;
                //说明到了0位置
            }else if(arrayKmp[t] == -1){
    
    
                s++;
                //否则的话找到target中最长前后缀相等的位置
            }else{
    
    
                t = arrayKmp[t];
            }
        }
        //如果找到位置则返回
        return t == target.length() ? s - target.length() : -1;
    }

    /**
     * 计算target中每个位置之前的kmp的前后缀最长相等数组
     * @param target
     * @return
     */
    private static final int[] getArrayKmp(String target){
    
    
        int[] kmp = new int[target.length()];
        kmp[0] = -1;kmp[1] = 0;int index = 0;
        for (int i = 2; i < target.length(); i++) {
    
    
            //记录index位置
            index = kmp[i - 1];
            //判断前一个位置和前一个位置的前缀长度位置是否相等---相等加一,不相等继续
            while (kmp[index] != -1 && !target.substring(index,index + 1).equals(target.substring(i - 1,i))){
    
    
                index = kmp[index];
            }
            if(target.substring(index,index + 1).equals(target.substring(i - 1,i))){
    
    
                kmp[i] = index + 1;
            }
        }
        return kmp;
    }

}

Guess you like

Origin blog.csdn.net/weixin_43795840/article/details/122097064