保留两个指针l 和r,以及一个哈希表M = character -> count 用于string2 中不出现在s[l..r] 中的字符。
初始设置l = 0 和r 以便string1[l..r] 包含string2 的所有字符(如果可能)。你可以通过从 M 中删除字符直到它为空来做到这一点。
然后在每个步骤中将r 加一,然后在保持 M 为空的同时尽可能地增加 l。所有r - l + 1(子字符串s[l..r]的长度)的最小值就是解决方案。
Pythonish 伪代码:
n = len(string1)
M = {} # let's say M is empty if it contains no positive values
for c in string2:
M[c]++
l = 0
r = -1
while r + 1 < n and M not empty:
r++
M[string1[r]]--
if M not empty:
return "no solution"
answer_l, answer_r = l, r
while True:
while M[string1[l]] < 0:
M[string1[l]]++
l++
if r - l + 1 < answer_r - anwer_l + 1:
answer_l, answer_r = l, r
r++
if r == n:
break
M[string1[r]]--
return s[answer_l..answer_r]
如果在执行递增和递减操作时保持正条目的数量,则可以在 O(1) 中实现“为空”检查。
设n 为string1 的长度,m 为string2 的长度。
请注意,l 和 r 只会递增,因此最多有 O(n) 次递增,因此在最后一个外循环中最多执行 O(n) 条指令。
如果M 被实现为一个数组(我假设字母是恒定大小的),你会得到运行时
O(n + m),这是最优的。如果字母表太大,您可以使用哈希表来获得预期的 O(n + m)。
示例执行:
string1 = "abbabcdbcb"
string2 = "cbb"
# after first loop
M = { 'a': 0, 'b': 2, 'c': 1, 'd': 0 }
# after second loop
l = 0
r = 5
M = { 'a': -2, 'b': -1, 'c': 0, 'd': 0 }
# increment l as much as possible:
l = 2
r = 5
M = { 'a': -1, 'b': 0, 'c': 0, 'd': 0 }
# increment r by one and then l as much as possible
l = 2
r = 6
M = { 'a': -1, 'b': 0, 'c': 0, 'd': -1 }
# increment r by one and then l as much as possible
l = 4
r = 7
M = { 'a': 0, 'b': 0, 'c': 0, 'd': -1 }
# increment r by one and then l as much as possible
l = 4
r = 8
M = { 'a': 0, 'b': 0, 'c': -1, 'd': -1 }
# increment r by one and then l as much as possible
l = 7
r = 9
M = { 'a': 0, 'b': 0, 'c': 0, 'd': 0 }
最好的解决方案是 s[7..9]。