Java + KMP 算法模板

Java + KMP 算法模板

public class KMP {

    /**
     * 求 next 数组
     * next 数组:匹配串当前下标的为结尾的后缀、最大能与从头开始的前缀匹配的个数
     * @param patternStr 匹配串(小串)
     */
    private static int[] getNext(StringBuilder patternStr) {
        int[] next = new int[patternStr.length()];

        int p = 0;
        for (int i = 1; i < patternStr.length(); i++) {
            char patCharI = patternStr.charAt(i);
            while (p > 0 && patternStr.charAt(p) != patCharI) {
                /**
                 * 核心跳转:(p - 1)为结尾的 next 个字符、与从头开始的 next 个字符与相匹配、也与 (i - 1)为结尾的 next 个字符相匹配
                 * 举例子:
                 * 下标:    0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
                 * 数组:    A A A A B A A B A A A  A  B  A  A  A
                 * next数组:0 1 2 3 0 1 2 0 1 2 3  4  5  6  7  3
                 * next[15]可以看出来,此时 i 为 15,p 为 7
                 */
                p = next[p - 1];
            }

            if (patCharI == patternStr.charAt(p)) {
                p++;
            }

            next[i] = p;
        }
        return next;
    }

    /**
     * kmp 根据 next 数组 进行匹配,直到文本串匹配结束
     * 返回文本串匹配上所有初始位置
     * @param matchStr 文本串(大串)
     * @param patternStr 匹配串(小串)
     * @param next next数组
     * @return
     */
    public List<Integer> KmpMatchTotal(String matchStr, String patternStr, int[] next) {
        List<Integer> res = new ArrayList<>();

        for (int i = 0, j = 0; i < matchStr.length(); i++) {
            while (j > 0 && matchStr.charAt(i) != patternStr.charAt(j)){
                j = next[j - 1];
            }


            if (matchStr.charAt(i) == patternStr.charAt(j)) {
                j++;
            }

            // 匹配成功
            if (j == patternStr.length()) {
                res.add(i + 1 - patternStr.length());
                // 继续寻找下一个
                j = next[j - 1];
            }
        }
        // 匹配结束
        return res;
    }
}
  • 7
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值