根据KMP算法实现String的indexOf方法

KMP算法详解参考链接

/**
 * 字符串工具类
 */
public class StringUtils {
    /**
     * 使用KMP算法获取指定字符串在目标字符串中最小的位置下标
     * <p>
     * 算法时间复杂度:O(n+m) <br/>
     * 例:str="abccbaabc", ptr="abc", result=0 <br/>
     * String的indexOf是暴力匹配,时间复杂度为O(n*m),某些情况下效率不会很高
     * </p>
     *
     * @see String#indexOf(String)
     * @param str 目标字符串
     * @param ptr 指定字符串
     * @return -1表示未找到
     */
    public static int indexOfByKMP(String str, String ptr) {
        if (str == null || ptr == null){
            return -1;
        }
        int sLen = str.length();
        int pLen = ptr.length();
        if (ptr.length() == 0) {
            return 0;
        }
        // 记录当前长度的字符串的最大前后缀长度,下标为0表示当前字符串长度为1
        int[] next = new int[pLen];
        // -1表示不存在相同的最大前缀和最大后缀
        next[0] = -1;
        // k记录当前匹配到的前后缀的长度
        int k = -1;
        // 将ptr字符串的对应子串的前后缀长度保存到next数组中
        for (int i = 1; i < pLen; i++) {
            // 如果下一个字符不匹配,那么k就变成next[k]
            while (k != -1 && ptr.charAt(k + 1) != ptr.charAt(i)) {
                // 往前回溯,next[k]始终<=k
                k = next[k];
            }
            if (ptr.charAt(k + 1) == ptr.charAt(i)) {
                k++;
            }
            // 获取当前子串的最大前后缀长度
            next[i] = k;
        }

        k = next[0];
        //
        for (int i = 0; i < sLen; i++) {
            while (k != -1 && str.charAt(i) != ptr.charAt(k + 1)) {
                // 回溯找到能匹配的最大前后缀和
                k = next[k];
            }
            if (str.charAt(i) == ptr.charAt(k + 1)) {
                k++;
            }
            // 完全匹配,返回结果
            if (k == pLen - 1) {
                return i - pLen + 1;
            }
        }
        return -1;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值