leetcode-28. 实现 strStr()

这道题有多种解法,先上最简单的解法,然后上稍复杂的解法。个人习惯上来就给复杂的展示,直接就把我劝退了。。

第一种:内置函数

class Solution {
    public int strStr(String haystack, String needle) {
		return haystack.indexOf(needle);
    }
}

第二种:双指针法

class Solution {
    public int strStr(String haystack, String needle) {
    	//根据题意,needle空串直接返回0即可
        if (needle == "")   return 0;
        int i = 0, j = 0;
        while (i < needle.length() && j < haystack.length()){
            char c = needle.charAt(i);
            char ch = haystack.charAt(j);
            if (c == ch){
            	//匹配同时往后移动
                i++;
                j++;
            }else {
	           //else是出现不匹配时的处理
	           //j - i 就表示回到第一个匹配的字符的下标位置
	           // 然后 + 1 表示从第一个匹配的字符的下一个再开始重新匹配。
	           //例如 : haystack = "abd"  needle = "abe" 当d和e不匹配时回到第一个匹配的a的位置,+1,从b开始重新匹配。
                j = j - i + 1;
                i = 0;
            }
            //返回第一个匹配的位置下标。
            if (i == needle.length()){
                return j - i;
            }
        }
        //没有匹配的返回-1
        return -1;
    }
}

第三种:kmp算法

观察下面的next数组的构造实现和kmp匹配方法的实现基本是相同的。
j :代表前缀的最后一个字符,同时还代表前后缀子串的最长匹配长度。
i : 代表后缀的最后一个字符。
当发生不匹配时,发生在后缀的后面,就要跳跃到前缀的后面,重新开始匹配。
需要理解好多概念:
啥是最长公共前后缀?
为啥只判断s【i】 和 s【j】 就能求出最长公共前后缀长度呢??
可能还有的会问为啥根据j = next【i】 来跳跃j呢??
借鉴Carl的视频理解,字面讲解很难理解 :https://www.bilibili.com/video/BV1PD4y1o7nd/?spm_id_from=333.788

class Solution {
    public int strStr(String haystack, String needle) {
        if(needle.equals("")){
            return 0;
        }
        int[] next = new int[needle.length()];
        getNext(next, needle);
        int j = 0;
        for(int i = 0; i < haystack.length(); ++i){
            while(j > 0 && haystack.charAt(i) != needle.charAt(j)){     //不匹配时j根据next表向前移动。
                j = next[j - 1];
            }
            if(haystack.charAt(i) == needle.charAt(j)){
                j ++;       //匹配就同时往后移动指针,这里只移动j即可, 因为i在for循环中移动
            }
            if(j == needle.length()){
                return i - needle.length() + 1;     //匹配的起始位置是i - needle.length() + 1.  可以自己举个例子看看确实是这样的。
            }
        }
        return -1;
    }
    public void getNext(int[] next, String needle){
        //这里使用不减一的操作。
        //还有使用统一减一的方法的,为什么使用统一减一的写法呢???
        //有什么好处,我不知道,没弄清楚
        int j = 0;                       //第一个字符的最长匹配长度肯定是0, 也是起始匹配位置 
        next[0] = j;
        for(int i = 1; i < needle.length(); ++i){
            while(j >= 1 && needle.charAt(i) != needle.charAt(j)){      //不匹配时,根据前缀表跳跃
                j = next[j - 1];
            }
            if(needle.charAt(i) == needle.charAt(j)){
                j ++;                   //匹配就同时往后移动
            }
            next[i] = j;        
        }

    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值