【力扣时间】【686】【中等】重复叠加字符串匹配

这是中等题?

1、先读题

请点我

读完题的第一想法是——介尼玛是中等题

2、审题

题目简单明了,且没有什么陷阱。
要说重点,似乎也没有什么重点。

毕竟我只想出了暴力。

总之,让我们直接快进到思路吧。

3、思路

我第一时间就想到了,这题肯定有简单的数学公式可以使用。但无奈,此时的我已经根本想不起来KMP算法了。

顺着题意我们肯定会想到,只要我们重复拼接字符串a,在逐步去判断b是否是新字符串的子串的话,这题就能迎刃而解了。

事实证明,这种基于暴力的简单直接的想法是可行的,当然耗时排名就没那么好看了。
于是,在基于暴力解决此题的思路下,我们面临了如下要点:

  1. 如何确认b必不可能是a的子串?
  2. 如何控制字符串a拼接的次数?

基于问题1,我们可以依次读取b字符串中的所有字符,并判断有没有a中不存在的字符。这种想法很容易实现,但出于耗时问题,就直接被我抛弃了。毕竟,在判断b是否为a的拼接字符串的子串过程中,就囊括了这个问题。

那么问题2呢?在我脑海里,是计划使用循环来控制拼接a字符串。于是这个问题也就变成了——如何控制跳出循环

我们来思考下如果b是a重复0~N次后的字符串的子串时,b会有哪些情况:

  1. 如果b.length()<= a.length()时,则b应该是a[i:end]+a[0:j]的情况。此时的答案显然是2。
  2. 如果b.length()>a.length()时,则b应该是a[i:end]+ N* a +a[0:j]的情况。此时的答案是N+2。

就如上两种情况,从第2条我们可以发现,a的重复字符的长度超过b后,最多还需要再拼接2次。如果2次还不行,辣么在多次都不可能实现,应当返回-1。

于是思路在此成型。

4、撸代码

class Solution {

    public int repeatedStringMatch(String a, String b) {
        StringBuilder sb = new StringBuilder(a);
        int ans = 1;

        while (sb.length() <= b.length() + 2 * a.length()) {

            if (sb.length() >= b.length() &&
                    sb.toString().contains(b)) {
                return ans;
            }

            sb.append(a);
            ++ans;
        }

        return -1;
    }
}

5、解读

就同我在思路中所说,我以StringBuilder来拼接字符串a,并且每次拼接后,都判断一下b是否是其子串。

if (sb.length() >= b.length() &&
        sb.toString().contains(b)) {
    return ans;
}

如果是的话,此时的ans便是答案对应的循环次数。

当循环跳出,仍然没有得到匹配子串成功的话,说明无法得出结果,即返回-1。

6、提交

在这里插入图片描述
因为是暴力,这种耗时排名甚至比预期还要高。
看来用暴力的人挺多的啊

7、咀嚼

啊这,这个该怎么分析啊……

8、受益匪浅

就如我先头所说,读完题我就知道了会有数学的解法,于是提交完暴力就直接跑去点题解了。

今天的题可以学的可太多了,首先是官解提供的两种算法——Rabin-Karp 算法 和 Knuth-Morris-Pratt 算法。

后者就是KMP了,这个我在大一时就学会,并一度用来刷过很多题的算法。然后……若干年的工作后,就忘得一干二净了。
毕竟大部分的业务场景都不会接触到这些东西……
曾经陪伴你的知识,就这样一点点被遗忘了。
不过忘了就再捡起来嘛!

当然,除了牛逼的公式算法,还有其他大牛分享的解法
其核心思路也与我的有异曲同工之妙,但有更优秀更值得学习的点。

9、总结

俗话说——黑猫白猫抓到耗子的就是好猫。
牛逼算法暴力解法,能够做出题目的都是好解法。

虽然今天的题我只能基于思路做出优化的暴力解法,但这种朴实无华的解法,能够让我在自己规定的时限内做出题目,也8是8行。

然后,官解的两种算法也很值得学习(算法的核心就是数学啊 ),对于这种公式化的数学算法,学会了往往能举一反三,一招刷遍所有类似的题。

啊……好忙……
社畜不想努力了,有没有富婆可以包养我啊……
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值