- 题目描述:
-
给定两个字符串 a 和 b,寻找重复叠加字符串 a 的最小次数,使得字符串 b 成为叠加后的字符串 a 的子串,如果不存在则返回 -1。
注意:字符串 “abc” 重复叠加 0 次是 “”,重复叠加 1 次是 “abc”,重复叠加 2 次是 “abcabc”。 -
示例:
-输入:a = “abcd”, b = “cdabcdab”
输出:3
解释:a 重复叠加三遍后为 “abcdabcdabcd”, 此时 b 是其子串。
输入:a = “abcd”, b = “cdabcdab”
输出:3
解释:a 重复叠加三遍后为 “abcdabcdabcd”, 此时 b 是其子串。
输入:a = “abc”, b = “wxyz”
输出:-1 -
提示
1 <= a.length <= 104
1 <= b.length <= 104
a 和 b 由小写英文字母组成 - 解析:这个问题可以拆解为两个部分来看,首先我们考虑最简单的情况,给定一个字符串a,b,判断b是不是a的子串,这个就很简单了,我们用一个很简单的滑动窗口就可以解决了。接下来我们在考虑a是一个可以变动的字符串,每次变动只能重复叠加其自身,这里有两种情况,如果b有a没有的字母,那么无论叠加多少次都会失败,第二种情况是b的字母a全有,但是b的字母顺序,a无论叠加多少次都不能匹配成果,比如a=“abcd”,b=“dca”,这种情况无论a叠加到多少次都是枉然,那么我们怎么判断这种情况从而让其终止叠加,返回匹配失败的结果呢?假设a的字符串长度是la,b的长度的lb,那么如果lb如果能在la的有限次重复中匹配成功,那么当其最小重复次数k,假设有已经有la*k(记为a1)>lb,那么lb一定能在a1*2中匹配成功,我们可以用反证法来证明,假设,b不能在a1*2匹配成功,在a1*3中匹配成功,那么其需要跨越三个a1,这显然不合理的,因为这违背了la*k>lb
- 所以那么lb一定能在a1*2中匹配成功
- 所以我们的终止条件就出来了k>2 and len(a*k)//2 > len(b),这里输入k>2是避免,a字符串一开始的长度就超过的b长度的两倍的情况。到这里题目答案就呼之欲出了,代码如下。
class Solution:
def repeatedStringMatch(self, a: str, b: str) -> int:
"""
给定两个字符串 a 和 b,寻找重复叠加字符串 a 的最小次数,使得字符串 b 成
为叠加后的字符串 a 的子串,如果不存在则返回 -1
>>>self.repeatedStringMatch( "abcd", "cdabcdab")
>>>3
"""
if len(set(a)) < len(set(b)):
return -1
def helpFuc(a, b):
"""
判断b是否是a的子串
>>>helpFuc("aab", "aa")
>>>True
>>>helpFuc("abc", "bd")
>>>False
"""
if len(a) < len(b):
return False
for i in range(len(a)-len(b)+1):
if a[i:i+len(b)] == b:
return True
return False
ans = 1
while True:
if helpFuc(a*ans, b):
return ans
else:
ans += 1
if ans > 2 and len(a*ans)//2 > len(b):
return -1