KMP算法代码思路,详解next数组的Java代码

本文深入探讨了KMP算法的代码实现,重点解析了next数组的生成过程。通过图文并茂的方式,阐述了如何从已知next[j]推导next[j+1],强调了在字符串不匹配时如何利用next数组回溯寻找最长相同前后缀。博客详细讲解了KMP算法的核心思想,并给出了完整的Java代码示例,帮助读者更好地理解和应用KMP算法。

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

KMP算法的思路请参考:kmp思想

能理解KMP的思想和能理解KMP代码是两回事,很多时候我们理解了思想,却看不懂代码实现,本篇博客主要是记录代码实现KMP的思路。
KMP算法的代码实现中,最重要也是最难理解的,就是next数组,下面直接上图:
首先,先假设我们已知了next数组的next[j]=k,意思就是j位置之前,由k-1个相同前后缀
在这里插入图片描述
接下来,在已知的前提下,推导j+1的情况,如果j向前一位变成j+1,之前的k位置S[k]如果等于S[j],那么next[j+1]=k+1
注意:这里是S[k]等于S[j],不是next

在这里插入图片描述
如果不相等,那么k就回溯到k=next[k]的值,因为next[k]中记录了k位置前面的最长相同前后缀,如果S[k]和S[j]不相等,那么k位置只能再往前找,看看k位置前面的相同前缀是否可以等于S[j]。因为next数组的功能就是来找最长相同前后缀的,而S[j]是后缀,那么前缀加上S[k]不能和S[j]相同,那么只能往前面找前面已经相同的前缀中,有没有能和S[j]这个后缀相同的。
上面这句话是KMP代码的核心思想,能理解这句话就能理解KMP的代码。
在这里插入图片描述
如果可以,就让next[j+1]=k+1,此时k其实是前面的next[k],如果k=next[k]也不行,那么就继续让k=next[k]
在这里插入图片描述
一直到出现相等。或者k=1时,因为next[1]=0,表示到头了。
在这里插入图片描述
这就是next数组的代码思想,下面是在代码中的具体体现:

public static boolean kmp(String str,String s){
        char[] T = str.toCharArray();
        char[] S = s.toCharArray();
        //定义next数组,next数组是根据短串生成的,别搞错了。
        //因为索引0没用到,因此数组长度加1
        int[] next=new int[s.length()+1];
        //定义两个指针
        int j=1;
        //表示前面j-1位置的next数组的值
        int k=0;
        //定义next[1]=0,next[1]=0表示短串已经回溯到头了,此时应该移动长串
        next[1]=0;
        //生成next数组,生成next数组的思路在图中详细解释
        while(j<s.length()){
            if(k==0||S[j-1]==S[k-1]){
                next[++j]=++k;
            }else {
                k=next[k];
            }
        }
        int i=1;
        int l=1;
        while (i<=T.length&&l<=S.length){
            //如果匹配成功,长串短串依次加1。
            //如果匹配失败,短串用next数组回溯,如果回溯到next[1]=0时,l=0,此时表示短串回溯到头了,
            //短串不能再回溯了,长串应该往后一位了(对应情况:如果第一位都不匹配,next[1]=0,长串应该后移一位)
            if(l==0||T[i-1]==S[l-1]){
                i++;
                l++;
            }else {
                l=next[l];
            }
        }
        //l>S.length说明上面的while循环是短串遍历完跳出来的,对应匹配成功的情况
        if(l>S.length){
            return true;
        }else {
            return false;
        }
    }
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值