Define S = [s,n]
as the string S which consists of n connected strings s. For example, ["abc", 3]
="abcabcabc".
On the other hand, we define that string s1 can be obtained from string s2 if we can remove some characters from s2 such that it becomes s1. For example, “abc” can be obtained from “abdbec” based on our definition, but it can not be obtained from “acbbe”.
You are given two non-empty strings s1 and s2 (each at most 100 characters long) and two integers 0 ≤ n1 ≤ 106 and 1 ≤ n2 ≤ 106. Now consider the strings S1 and S2, where S1=[s1,n1]
and S2=[s2,n2]
. Find the maximum integer M such that [S2,M]
can be obtained from S1
.
Example:
Input:
s1="acb", n1=4
s2="ab", n2=2
Return:
2
---------------------------------------------------------------------------------
这题最开始的想法是把s1*n1和s2*n2全部展开,这样复杂度为O(max(s1*n1,s2*n2))
再进一步简化,数一下s1*n1里面有多少个s2即可,最后除一下n2,复杂度O(max(s1*n1,s2))
后面才意识到这题的考点是怎么简化n1,上面两种方法都会超时。。。
简化的思路是观察下面一段匹配代码,index的变化会出现周期性,当上次(s1pre,s2pre)匹配到s2的index时,下次(s1cnt,s2cnt)一直匹配下去还会匹配到s2的index,此后一直循环,类似于无限循环小数的循环节。。。因此,循环前有零头,循环后也可能有零头,再加上中间循环的,就是结果。
s1cnt, index, s2cnt = 0, 0, 0
while True:
s1cnt += 1
for ch in s1:
if ch == s2[index]:
index += 1
if index == len(s2):
s2cnt, index = s2cnt + 1, 0
注意每次s1完整的遍历完一遍,都会有对应的s2cnt和index变化,如果index遍历了len(s2)+1次还没有循环,那是不可能的,因为鸽巢原理(即使s1没法完全覆盖s2,index走不到头,index的值也会很快循环)。最终的代码如下:
class Solution:
def getMaxRepetitions(self, s1: str, n1: int, s2: str, n2: int) -> int:
l1,l2,s1cnt,s2cnt,index,dic,res = len(s1),len(s2),0,0,0,{},0
while (True):
s1cnt+=1
for ch in s1:
if (ch == s2[index]):
index += 1
if (index == l2):
index,s2cnt = 0, s2cnt+1
if (index not in dic):
dic[index] = (s1cnt,s2cnt)
else:
(s1pre,s2pre) = dic[index]
res = s2cnt+(n1-s1cnt)//(s1cnt-s1pre)*(s2cnt-s2pre) #bug2: res = s2pre+(n1-s1cnt)//(s1cnt-s1pre)*(s2cnt-s2pre)
print('s1pre={0} s2pre={1} s1cnt={2} s2cnt={3} res={4}'.format(s1pre, s2pre, s1cnt, s2cnt, res))
break
if (s1cnt == n1): #bug1: s1cnt == n2+1
return s2cnt // n2
for _ in range((n1-s1cnt) % (s1cnt-s1pre)):
for ch in s1:
if (ch == s2[index]):
index += 1
if (index == l2):
index,res = 0, res+1
return res//n2