算法修炼之路—【字符串】Leetcode 686 重复叠加字符串匹配

题目描述

给定两个字符串AB,寻找重复叠加字符A的最小次数,使得字符串B成为叠加后的字符串A的子串,如果不存在则返回-1.

示例:

输入: A = “abcd”, B = “cdabcdab”
输出: 3
解释: A重复叠加三遍后为"abcdabcdabcd",此时B是其子串; A 重复叠加两边后为“abcdabcd”,B并不是其子串。

注意: AB字符串的长度在110000区间范围内。

思路分析

题目难度为简单 ,这里简化题目意思就是输入字符串存在子母串关系前提下,如何判断A的最小重复次数,如图1,图2 所示,这里我们可以将情况分为两种:

  1. B占据kA的中间部分;
  2. B至少占据kA一端(开头或结尾)字符;
    在这里插入图片描述
    图1 情况1示意图

在这里插入图片描述
图2 情况2示意图

这里,我们进一步分析可知,若BA的子串,则会在叠加A后的子串长度小于等于2倍B字符串长度内检测到,故这里直接给出代码核心部分:

代码片1

		StringBuiler strs = new StringBuilder(a);
		int res = 1;
		
        while(strs.length() < b.length()*3){ // or <= b.length() * 2
            if(strs.indexOf(b) >= 0)
                return res;
            else{
                strs.append(a);
                res++;
            }
        }

情况完善

在上面的思考过程中,我们会发现仅适用于a.length() <= b.length()的情况,如果a.length() > b.length(),我们需要判断当strs.length() < a.length()*3的情况(这里不做详细说明,可自行绘图):

  1. BA的中间子串,则在首次while循环(仅叠加了一次)时,返回1;
  2. B占据A的至少一端,则至多在第二次while循环(叠加了两次)时,则会发现;

即当A.length() > B.length()时,不存在当B确实为A,但两次叠加A后无法检测的情况,故这里while循环设置为while(strs.length() < a.length()*3)。这时核心代码变成:

代码片2

        while(strs.length() < a.length()*3){ // or <= a.length() * 2
            if(strs.indexOf(b) >= 0)
                return res;
            else{
                strs.append(a);
                res++;
            }
        }

情况合并

此时,我们比较代码片1代码片2,试图将其进行规整,我们发现while循环条件均为strs.length() < x * 3,这里的x为输入字符串a,b的最长者,则我们可以设置一基准长度baseLen,将while循环条件变量化:

        int baseLen = Math.max(a.length(), b.length());
        
        while (strs.length() < baseLen * 3) {
            if (strs.indexOf(b) >= 0) {
                return res;
            } else {
                strs.append(a);
                res++;
            }
        }

进一步节省空间,我们直接将变量baseLen省略,则有最终的解题代码:

解题代码

    public static int solution(String a, String b) {
    
		int res = 1;
        StringBuilder strs = new StringBuilder(a);
        
        while (strs.length() < 3 * Math.max(a.length(), b.length())) {
        
            if (strs.indexOf(b) >= 0) {
                return res;                
            } else {
                strs.append(a);
                res++;
            }
        }

        return -1;

    }

复杂度分析

我们设n,mA,B的字符串长度

时间复杂度: 检测B是否为子串时,其时间复杂度为O(m)strs的长度最长为2max(n, m),故时间复杂度为O(m*max(n, m));
空间复杂度: 我们借助了StringBuiler strs的辅助,且最长为2max(n, m),故空间复杂度为O(max(n, m));

Github源码

完整可运行文件请访问GitHub

猜你喜欢

转载自blog.csdn.net/u011106767/article/details/106162410