text of Alice in Wonderland包含8次“仙境”这个词。 (让我们对这个问题不区分大小写)。
然而,如果你计算非连续的子序列以及子串,它会多次包含这个词,例如。
要么井很深,要么她很慢,因为她有 她有很多时间去看她和 WONDER 是什么 接下来会发生。首先,她试图 L ook down AND 弄明白了 她来了,但是看不到任何东西太黑了;
(子序列是一个序列,可以通过删除一些元素而不改变其余元素的顺序从另一个序列派生。-Wikipedia)
这本书包含仙境这个词作为一个子序列多少次?我希望这将是一个很大的数字 - 这是一本很长的书,有许多w和o和n和s。
我尝试了强力计数(递归使得循环10深)但它太慢了,即使对于那个示例段落也是如此。
答案 0 :(得分:10)
我们假设您不想搜索var message = new Buffer('HIA');
udpServer.send(message, 0, message.length, ...)
,而只是wonderland
。然后,您只需计算故事中w
发生的次数。
现在让我们说你想要w
。对于您找到的当前模式的每个第一个字符,您可以添加到计数中:
在故事的其余部分出现没有第一个字符的当前模式的次数,在此字符之后:您已将问题wo
简化为{{1} }
整个当前模式在故事的其余部分出现了多少次。因此,您已将问题缩减为(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
在其之后发生一次。< / p>
对于第二个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
出现的次数。
这允许使用memoization进行动态编程:
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]
致电。请注意,您可以使代码更清晰(删除重复的函数调用)。
Python代码,没有任何记忆:
count(0, 0, dp)
输出:
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
中的每个i
个第一个字符,您可以将其与第二个wonderland
中剩余的最终字符进行分组,为您提供{{1解决方案。另一个wonderland
是单词本身。其他五个是:
10
你是对的,这将是一个巨大的数字。我建议您使用大整数或以模数形式取结果。
同一程序会为您的示例段落返回2
。
答案 1 :(得分:3)
字符串“wonderland”作为 Alice in Wonderland 1 24100772180603281661684131458232次的子序列出现。
主要思想是逐个字符地扫描主文本,保持目标字符串的每个前缀的频率的运行计数(即:在这种情况下,“w”,“wo”,“won”,... 。,“wonderlan”和“仙境”)已经发生在当前的信件中。这些运行计数易于计算和更新。如果当前的字母没有出现在“仙境”中,则计数保持不变。如果当前的字母是“a”,那么我们增加“wonderla”的数量,看看到目前为止看到的“wonderl”的数量。如果当前字母是“n”,那么我们将“won”的计数增加“wo”的计数,并将“wonderlan”的计数增加“wonderla”的计数。等等。当我们到达文本的末尾时,我们将根据需要计算“wonderland”的所有前缀,包括字符串“wonderland”本身。
这种方法的优点是它需要单次传递文本,并且不需要O(n)递归调用(除非你做一些聪明的事情,否则它可能超过最大递归深度。)
import fileinput
import string
target = 'wonderland'
prefixes = dict()
count = dict()
for i in range(len(target)) :
letter = target[i]
prefix = target[:i+1]
if letter not in prefixes :
prefixes[letter] = [prefix]
else :
prefixes[letter].append(prefix)
count[prefix] = 0L
for line in fileinput.input() :
for letter in line.lower() :
if letter in prefixes :
for prefix in prefixes[letter] :
if len(prefix) > 1 :
count[prefix] = count[prefix] + count[prefix[:len(prefix)-1]]
else:
count[prefix] = count[prefix] + 1
print count[target]
答案 2 :(得分:0)
对以前的评论进行跟进,如果您正在寻找一个针对2
输入wonderlandwonderland
而针对1
返回wonderwonderland
的算法,那么我认为您可以从这个问题中调整算法:
How to find smallest substring which contains all characters from a given string?
实际上,你的案例的变化是,一旦找到一个单词的实例,你就增加一个计数器并用文本的剩余部分重复所有的程序。
当O(n)
是文本的长度时,此类算法将n
及O(m)
在空格中m
是搜索字符串的长度。