LeetCode686——Repeated String Match
题目:
Given two strings A and B, find the minimum number of times A has to be repeated such that B is a substring of it. If no such solution, return -1. For example, with A = "abcd" and B = "cdabcdab". Return 3, because by repeating A three times (“abcdabcdabcd”), B is a substring of it; and B is not a substring of A repeated two times ("abcdabcd"). Note: The length of A and B will be between 1 and 10000.
理解:
给出两个字符串,找到A重复的最小次数,使得B字符串是A重复后的子字符串,如果没有答案则返回-1。
举个例子,A="abcd",B = "cdabcdab",返回结果 3, 因为A重复三次以后,"abcdabcdabcd",此时B就是A的一个子字符串了,而且3是最小的重复次数,因为重复两次的时候“abcdabcd”不能使B成为A的子字符串。
注意:A和B字符串的长度在1到10000之间
原始解题思路:
建立一个循环,记录循环次数,拼接A字符串为C,然后判断B是否在C内,如果存在则输出循环次数,如果不同,则继续循环。
如果C的长度大于10000,则返回-1。
python 代码:
def repeatedStringMatch(A, B): i = 1 C = A while(1): if B in C: return i else: i = i + 1 C = C + A if len(C) > 10000: return -1
验证结果:
Runtime: 240 ms, faster than 18.07% of Python3 online submissions for Repeated String Match.
Memory Usage: 13.3 MB, less than 5.19% of Python3 online submissions for Repeated String Match.
改进思路:
- 尽可能减少循环次数
有一点很重要,那就是究竟A重复多少次可以确定B一定不是A的子字符串,
举个例子,A="abca",B="aa",可以看到A重复一次B就可以成为子字符串,那是因为A的首和尾叠加了,使得B的两个字符成功衔接起来。
第二个例子:A =“abca”与B = “caab”,同样也是一次。
最多重复次数应该与A和B的长度都有关系,在第二个例子中,A与B的长度相同,如果A重复了一次还没有得到结果,那么可以断定,A再重复自己也不能使得B成为子字符串
首先假设B的长度是A的长度的n倍(取整)。
根据第二个例子举例:
依然假设B的长度为4,那么无论A重复多少次,B都是一个在A重复多次后的字符串(假设为C)上长度为4的滑动窗口,
A = abca
B = 长度为4的字符串
n = 1
n = 1
abcaabcaabca
abcaabcaabca
……依次类推,可以看到B共有3个可能性,看到这里一部分人可能想到了,B的长度越长,意味着滑动窗口可能占用的重复字符串数越多,
继续举例:
A = abca
B = 长度为10的字符串
n = 2
n = 2
abcaabcaabca
abcaabcaabca
abcaabcaabca
写到这里,很明显的发现三次循环已经无法适用于n等于2的情况了,只有当四次循环的时候才可能包括所有的B字符串可能的组合结构。
简单归纳起来,我们可以发现,A字符串最多需要重复n+2次即可确定是否有结果,因此改进程序:
def repeatedStringMatch(A, B): C = "" for i in range(int(len(B)/len(A))+ 3): if B in C: return i C += A return -1
验证结果:
Runtime: 152 ms, faster than 68.14% of Python3 online submissions for Repeated String Match.
Memory Usage: 13.1 MB, less than 5.19% of Python3 online submissions for Repeated String Match.