KMP算法--Java实现

本文深入讲解了Knuth–Morris–Pratt (KMP) 字符串搜索算法的实现原理及代码细节。通过实例演示了如何高效地进行字符串匹配,并介绍了next数组的构造方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

看了很多大牛写的文章,才敢把自己理解的写出来。
http://www.ruanyifeng.com/blog/2013/05/Knuth–Morris–Pratt_algorithm.html
https://www.cnblogs.com/yjiyjige/p/3263858.html

/**
 * @author Ravanla
 * @create 2019-04-03-21:10
 */
public class KMP {
    public static void main(String[] args){
        String s1 = new String("ABBXABBCDFS");
        String s2 = new String("ABBC");
        System.out.println(KMP(s1, s2));
    }

    public static int KMP(String ts, String ps){
        char[] t = ts.toCharArray();
        char[] p = ps.toCharArray();
        int i = 0;
        int j = 0;
        int[] next = getNext(ps);
        while (i < t.length && j < p.length) {
//            如果t和p中位置匹配了,就让它们的下标都往下一位挪然后去比较,当然j又要回到开头时也要让他们的下标往下一位移
            if(j == -1 || t[i] == p[j]){
                i++;
                j++;
            }
//            否则,让当前j的位置知道自己要让前面的谁代替,next就是记录不匹配的时候哪个下标要去它那个位置的
            else{
                j = next[j];
            }
        }
//        如果j到它的字符数组长度了,说明在t找到了有与p完全相同的字串,i - j我们可以这样想
//        当j == p.length时 i == j  他们在同一个位置,我们要知道p的开头对在t的哪里的话就只需要 i - j
        if(j == p.length){
            return i - j;
        }
        else {
            return -1;
        }
    }

    public static int[] getNext(String ps){
        char[] p = ps.toCharArray();
        int[] next = new int[p.length];
        next[0] = -1;
        int k = -1;
        int j = 0;

        while (j < p.length - 1) {
            if(k == -1 || p[j] == p[k]){
//            k   j
//                A   A   A   C   A   A
//               -1   ?   ?
//               当两个字符相等时要跳过
                if (p[++j] == p[++k]) {
                    next[j] = next[k];
                }
//            k   j
//                A   B   C
//               -1   ?   ?
//                这里不相等k也会++ , j也是
                else {
                    next[j] = k;
                }
            }
            else{
                k = next[k];
            }
        }
//        打印数组看一下
        System.out.println("next数组:");
        for(int i:next){
            System.out.print(i + " ");
        }
        System.out.println();

        return next;
    }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值