【KMP】通过最长前后缀存储中间变化---可适用于汉字匹配等

补充上一版本的KMP只能兼容字符数字的情况

代码中有注解—不对的地方请指出共同学习

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;
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值