更确切地说,我正在寻找一种算法,它将采用两个字符串集合,并返回第一个集合中包含第二个集合中所有元素的所有元素。
e.g。如果我有[“猫”,“狗”,“男孩”],它会回来说,“男孩想要一只猫和一只狗”,但不是,例如,“狗是个好孩子。” / p>
我找到了Aho-Corasick算法,但对于“至少一个匹配”而不是“每个匹配”解决方案似乎更好。
答案 0 :(得分:0)
我不确定问题的具体细节,但假设你有
collection1 : ['this is a good boy',' this is a bad boy',....]
和
collection2: ['this', 'is a', 'good', 'boy']
它应该只返回'this is a good boy'
。
同样,我不确定这种算法的内存和速度要求,但我会创建一个后缀树来验证元素的存在:
伪造的代码
for elm1 in collection1:
sTree = suffix_tree(elm)
valid = false
for elm2 in collection2:
valid = valid & search_in_suffix(elm2)
if valid:
return elm1
return 'NOT_FOUND'
您可以阅读有关后缀树here的更多信息。请记住,它还取决于您的数据集,如果您有非常大的字符串,后缀树可能很快但创建它会花费您大量的内存。
答案 1 :(得分:0)
如果我们略微修改它,Aho-Corasick自动机可以在这里工作。
让我们为第二个字符串集合构建Aho-Corasick自动机。
如果自动机中的一个字符串是另一个字符串的前缀,我们可以删除它。它不会改变答案。
让我们仅使用初始边缘(它以这种方式树)来遍历自动机并预先计算一个节点,该节点是给定节点的祖先,并且对应于来自该节点的某个字符串的末尾。每个节点的集合(我将其表示为anc_end
。它是唯一的,因为没有字符串是任何其他节点的前缀,如上所示)。我们可以使用深度优先搜索在线性时间内完成它(参数是当前节点和最后一个节点,它们对应于我们在从根节点到此节点的路径上看到的某些字符串的结尾(或者,如果是-1,则为-1)没有这样的节点))。
我们可以像通常对第一个集合的每个字符串一样遍历自动机。我们需要在was[anc_end[v]] = true
是当前节点的每个步骤设置v
。我们只需检查was
是true
是否与我们完成后第二个集合中某些字符串结尾对应的所有节点都有was
。
我们几乎就在那里。我们不会使用新集合为每个字符串初始化NA
数组,而是使用"数组与版本"结构(想法是保持一对(值,时间戳)而不仅仅是值,并在我们转到下一个字符串时递增计时器))并计算所见的"结束"节点(我们需要为第一个集合中的每个字符串将计数器重置为零)。
此解决方案在输入大小上是线性的,因此它在时间复杂度方面是最优的(它也使用线性空间量)。