保持两个指针l和r,以及一个哈希表M=字符->计数,用于存储字符串2中不在s[l..r]中出现的字符。
最初将l设置为0,并设置r,使得string1[l..r]包含所有string2的字符(如果可能的话)。通过从M中删除字符直到为空来实现这一点。
然后,每次将r递增1,然后尽可能多地递增l,同时仍保持M为空。所有r-l+1(子串s[l..r]的长度)中的最小值即为解决方案。
Pythonish伪代码:
n = len(string1)
M = {}
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"
M = { 'a': 0, 'b': 2, 'c': 1, 'd': 0 }
l = 0
r = 5
M = { 'a': -2, 'b': -1, 'c': 0, 'd': 0 }
l = 2
r = 5
M = { 'a': -1, 'b': 0, 'c': 0, 'd': 0 }
l = 2
r = 6
M = { 'a': -1, 'b': 0, 'c': 0, 'd': -1 }
l = 4
r = 7
M = { 'a': 0, 'b': 0, 'c': 0, 'd': -1 }
l = 4
r = 8
M = { 'a': 0, 'b': 0, 'c': -1, 'd': -1 }
l = 7
r = 9
M = { 'a': 0, 'b': 0, 'c': 0, 'd': 0 }
最佳的解决方案是 s[7..9]。
O(n^2)
,而是O(n^3)
- 检查每个子字符串本身就是O(n)
,而这些子字符串有O(n^2)
个。除非你有其他想法? - amith
。 - Niklas B.string1
中最小的子字符串,其字符的多重集合是string2
字符的多重集合的超集。从问题中的语句“lo ho
是唯一包含string2
所有字符的子字符串”必须是一个错误,否则对我也毫无意义。 - Niklas B.