【Leetcode刷题指南】字符串匹配问题之实现 strStr()

CSDN话题挑战赛第1期
活动详情地址:https://marketing.csdn.net/p/bb5081d88a77db8d6ef45bb7b6ef3d7f
参赛话题:Leetcode刷题指南
话题描述:代码能力是一个程序员的基本能力,而除了做项目之外,大家接触到的最常规的提升代码能力的方法基本就是刷题了,因此,加油刷题,冲刺大厂!
创作模板:Leetcode刷题指南



💎一、实现 strStr()

🏆1.题目描述

判断一个字符串是不是另一个字符串的子串,子串出现的第一个位置。不存在就返回-1
输入:haystack = “hello”, needle = “ll”
输出:2

🏆2.原题链接

https://leetcode.cn/problems/implement-strstr/

💎二、解题报告

🏆1.思路分析

🔑思路1:最简单的方法就是暴力遍历,遍历haystack 所有长度和needle 相同的子串, 时间复杂度O(n * m)

找子串这么经典的字符串匹配问题,怎么能只会暴力遍历呢?

🔑思路2:Rabin-Karp算法, 具体算法原理,已经更多练习可以看我这篇博文:https://blog.csdn.net/weixin_44179010/article/details/122081259

终极经典,不好记,不好理解,但是却很牛逼的算法。

🔑思路3:KMP算法, 等会会给出详解

🏆2.代码详解

方法一:暴力遍历

借助两个库函数可以拿到100%, 但是原因是测试用例的问题。 这个时间复杂度O(m * n) 还是比较大的

        for(int i = 0; i <= haystack.length() - needle.length(); i++) {
            if(haystack.substring(i, i + needle.length()).equals(needle)) return i;
        }
        return -1;

方法二:Rabin-Karp 算法

主要原理是计算子串Hash值,然后以O(n)的时间复杂度获取到主串长度为m的子串的hash值,hash值相同再比较每个字符是否相同。时间复杂度O(n + m)。 时间100%
代码可能较长,但都很简单,很好理解

    public int strStr(String haystack, String needle) {
        //Rabin - karp
        int MOD = 100000009;
        int base = 31;  //小写字母共26个,必须是比26大的映射。 选择质数31降低偶然性
        int srcLen = haystack.length(), tarLen = needle.length();
        //计算最高位权重, 这个必须用 long 防止溢出
        long highWeight = 1;  
        //注意这里只需要乘tarLen - 1 次就行了
        for(int i = 0; i < tarLen - 1; i++) {
            highWeight = (highWeight % MOD * base) % MOD;
        }

        //计算子串hash值
        long tarHash = 0;
        for(int i = 0; i < tarLen; i++) {
            tarHash = (tarHash * base % MOD + (needle.charAt(i) - 'a')) % MOD;
        }
        //System.out.println("highWeight=" + highWeight + ", tarHash=" + tarHash);
        //遍历计算主串长度和子串相同的 hash值
        long srcHash = 0;
        for(int i = 0; i < srcLen; i++) {
            srcHash = (srcHash * base % MOD + (haystack.charAt(i) - 'a')) % MOD;
            //System.out.println(srcHash);
            if(i >= tarLen - 1) {
                if(srcHash == tarHash) {
                    //hash值相同,逐个字母比较
                    boolean flag = false;
                    for(int j = 0; j < tarLen; j++) {
                        if(haystack.charAt(i - tarLen + 1 + j) != needle.charAt(j)) flag = true;;
                    }
                    if(!flag) return i - tarLen + 1;
                }
                //减去最高位的
                srcHash = (srcHash - highWeight * (haystack.charAt(i - tarLen + 1) - 'a') % MOD) % MOD;
                if(srcHash < 0) srcHash += MOD;
            }
        }
        return -1;
    }

方法三:KMP算法

待补充…

🏆3.KMP

KMP算法的核心是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。
核心是next数组, next数组包含的是前缀字符串 和 后缀后缀字符串相同的最大长度


CSDN话题挑战赛第1期
活动详情地址
:https://marketing.csdn.net/p/bb5081d88a77db8d6ef45bb7b6ef3d7f

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

甲 烷

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值