如果不允许重叠,这个问题就会变得比最初看起来要困难得多。
据我所知,没有其他答案是正确的(见最后的测试用例)。
之所以需要递归,是因为如果一个子字符串出现多次,使用一次而不是另一次可能会阻止找到其他子字符串。
这个答案使用两个函数。第一个查找字符串中子字符串的每一次出现,并返回字符串的迭代器,其中子字符串已被替换为不应出现在任何子字符串中的字符。
第二个函数递归检查是否有办法找到字符串中的所有数字:
def find_each_and_replace_by(string, substring, separator='x'):
"""
list(find_each_and_replace_by('8989', '89', 'x'))
# ['x89', '89x']
list(find_each_and_replace_by('9999', '99', 'x'))
# ['x99', '9x9', '99x']
list(find_each_and_replace_by('9999', '89', 'x'))
# []
"""
index = 0
while True:
index = string.find(substring, index)
if index == -1:
return
yield string[:index] + separator + string[index + len(substring):]
index += 1
def contains_all_without_overlap(string, numbers):
"""
contains_all_without_overlap("45892190", [89, 90])
# True
contains_all_without_overlap("45892190", [89, 90, 4521])
# False
"""
if len(numbers) == 0:
return True
substrings = [str(number) for number in numbers]
substring = substrings.pop()
return any(contains_all_without_overlap(shorter_string, substrings)
for shorter_string in find_each_and_replace_by(string, substring, 'x'))
这里是测试用例:
tests = [
("45892190", [89, 90], True),
("8990189290", [89, 90, 8990], True),
("123451234", [1234, 2345], True),
("123451234", [2345, 1234], True),
("123451234", [1234, 2346], False),
("123451234", [2346, 1234], False),
("45892190", [89, 90, 4521], False),
("890", [89, 90], False),
("8989", [89, 90], False),
("8989", [12, 34], False)
]
for string, numbers, should in tests:
result = contains_all_without_overlap(string, numbers)
if result == should:
print("Correct answer for %-12r and %-14r (%s)" % (string, numbers, result))
else:
print("ERROR : %r and %r should return %r, not %r" %
(string, numbers, should, result))
以及对应的输出:
Correct answer for '45892190' and [89, 90] (True)
Correct answer for '8990189290' and [89, 90, 8990] (True)
Correct answer for '123451234' and [1234, 2345] (True)
Correct answer for '123451234' and [2345, 1234] (True)
Correct answer for '123451234' and [1234, 2346] (False)
Correct answer for '123451234' and [2346, 1234] (False)
Correct answer for '45892190' and [89, 90, 4521] (False)
Correct answer for '890' and [89, 90] (False)
Correct answer for '8989' and [89, 90] (False)
Correct answer for '8989' and [12, 34] (False)