假设您不想搜索wonderland,而只想搜索w。然后您只需计算故事中出现了多少次w。
现在假设你想要wo。对于您找到的当前模式的每个第一个字符,您将添加到计数中:
-
没有第一个字符的当前模式在故事的其余部分中出现了多少次,在你所在的这个字符之后:所以你已经将问题(story[1..n], pattern[1..n])减少到(story[2..n], pattern[2..n])
整个当前模式在故事的其余部分出现了多少次。所以你把问题减少到(story[2..n], pattern[1..n])
现在您只需将两者相加即可。如果我们从子问题的角度来讨论,就不会多计。考虑示例wawo。显然,wo 出现了2 次。你可能会认为计数会是这样的:
对于第一个w,添加1,因为o在它之后出现一次,另一个1因为wo在它之后出现一次。
对于第二个w,添加1,因为o 在它之后出现一次。
答案是3,这是错误的。
但这就是实际发生的情况:
(wawo, wo) -> (awo, o) -> (wo, o) -> (o, o) -> (-, -) -> 1
-> (-, o) -> 0
-> (awo, wo) -> (wo, wo) -> (o, wo) -> (-, wo) -> 0
-> (o, o) -> (-, -) -> 1
-> (-, o) -> 0
所以你可以看到答案是2。
如果您没有找到w,那么这个位置的计数就是wo 在这个当前字符之后出现的次数。
这允许使用记忆进行动态编程:
count(story_index, pattern_index, dp):
if dp[story_index, pattern_index] not computed:
if pattern_index == len(pattern):
return 1
if story_index == len(story):
return 0
if story[story_index] == pattern[pattern_index]:
dp[story_index, pattern_index] = count(story_index + 1, pattern_index + 1, dp) +
count(story_index + 1, pattern_index, dp)
else:
dp[story_index, pattern_index] = count(story_index + 1, pattern_index, dp)
return dp[story_index, pattern_index]
拨打count(0, 0, dp)。请注意,您可以使代码更简洁(删除重复的函数调用)。
Python 代码,没有记忆:
def count(story, pattern):
if len(pattern) == 0:
return 1
if len(story) == 0:
return 0
s = count(story[1:], pattern)
if story[0] == pattern[0]:
s += count(story[1:], pattern[1:])
return s
print(count('wonderlandwonderland', 'wonderland'))
输出:
17
这是有道理的:对于故事的第一个 wonderland 中的每个 i 第一个字符,您可以将其与第二个 wonderland 中的剩余最终字符分组,为您提供 10 解决方案。另一个2 是单词本身。其他五个是:
wonderlandwonderland
********* *
******** **
******** * *
** ** ******
*** * ******
你说得对,这将是一个巨大的数字。我建议您要么使用大整数,要么将结果取模。
相同的程序为您的示例段落返回9624。