Leetcode 实现strStr()函数(KMP)

Leetcode 实现strStr函数(KMP)


实现 strStr() 函数。

给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。如果不存在,则返回 -1。

示例 1:

输入: haystack = “hello”, needle = “ll”
输出: 2

示例 2:

输入: haystack = “aaaaa”, needle = “bba”
输出: -1

说明:

当 needle 是空字符串时,我们应当返回什么值呢?这是一个在面试中很好的问题。

class Solution {
    public int strStr(String haystack, String needle) {
        int[] next = Getnext(needle);
        if(haystack == null) return -1;//剪枝
        if(next[0] == -1||needle == null) return 0;//leetcode用例 "","",进行输出
        int j = 0;
        int i = 0;
        while(i < haystack.length()){
            if(haystack.charAt(i) == needle.charAt(j)){//如果对比字符相同haystack和needle的指针向后移
                i++;
                j++;
            }
            if(j == needle.length()){
                return i - j;
            }
            else if(i < haystack.length()&&haystack.charAt(i) != needle.charAt(j)){//字符不匹配
                if(j != 0){//needle的指向未在首字符处,就通过next数组的字符串前后缀匹配,向前移动,进行下一次的字符匹配
                    j = next[j - 1];
                }
                else//没有公共前缀,直接让haystack的字符与needle的首字符对比
                    i++;
            }
        }
        return -1;
    }
    /*
    next数组,寻找needle的公共前后缀,在某个字符处不匹配时,
    就找出它之前的字符串的最大公共前后缀,在haystack与needle
    对比时,将needle的指向移向公共前缀后的一个字符,haystack的
    指向位置不变,两个字符再进行对比。
    */
    public int[] Getnext(String needle){
        if(needle.length() > 0){//防止空字符串
            int[] next = new int[needle.length()];
            next[0] = 0;//人为设置,开头未匹配,就从needle的首字符对比
            int j = 0, i = 1;//两个指向来判断是否是公共前后缀
            while(i < needle.length()){
            	/*
            	如果两个字符相同,i,j都向后移动next[i]存储
            	在needle.charAt(i)处不匹配时,needle不用回溯
            	通过next[i]来定位needle在下一次对比时指向
            	(记录最大公共前缀后的一个字符的位置)
            	*/
                if(needle.charAt(i) == needle.charAt(j)){
                    j++;
                    next[i] = j;
                    i++;
                }
                else{
                /*
                如果j指向在needle的首字符,i就往后找公共前后缀
                在进行对比时,此处不匹配的话,就从needle的首字符对比
                */
                    if(j == 0){
                        next[i] = 0;
                        i++;
                    }
                    else{
                    //如果在此处不一样就看之前的字符串的
                    //最大公共前后缀
                        j = next[j - 1];
                    }
                }
            }
            return next;
        }
        int[] next = {-1};
        return  next;
        
    }
}

执行结果:
通过
显示详情
执行用时:11 ms, 在所有 Java 提交中击败了7.99% 的用户
内存消耗:39.8 MB, 在所有 Java 提交中击败了21.59% 的用户

总结

实现kmp算法时,先找needle的next数组,找各个字符与之前字符串的最大公共前后缀,可以不用每次都必须进行回溯,最后进行haystack与needle的字符匹配。kmp算法的优势就是每次匹配不成功时needle不用每次都回溯至首字符,减少比较次数。

主要参考了题解中带佬的讲解,带佬的题解地址,其中附加的三哥讲解的next数组挺好的
有什么不对的地方,还望在评论区指出。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值