递归 - 如何从特定遍历中提取

时间:2011-11-14 13:49:54

标签: python algorithm recursion

假设你有一个字符串:abcde

一组字符串:ab,cde,abcd,a,bcd,cd

您希望从形成字符串的集合中找到所有可能的连接。

您可以使用递归遍历集合中的所有可能的连接,但是如何仅返回满足解决方案的那些?

可能的组合:

ab - cde - yes
ab - cd - no
abcd - no
a - bcd - no
ab - cd - no

您可以从遍历构建树,然后提取完成的路径。有没有使用树的方法?

我在Python中实现它,但可以用任何语言回答。

3 个答案:

答案 0 :(得分:3)

使递归函数返回所有连接的列表。

即,您创建了一个函数concatenations,其中包含一个字符串和一个集合作为输入。此函数返回适合字符串的集合中所有项目串联的列表。

然后你可以用自己的方式递归地定义concatenations

  • (结束条件)如果字符串为空,则任何集合都满足条件,因此返回一个包含单个空的连接的列表。

    concatenations("", any set) = [[]]   # single empty concatenation
    
  • (递归调用)否则,组成字符串的集合元素的连接集可以定义为集合的元素X与所有连接的串联删除了X的字符串(从开头)和删除了X的字符串,用于字符串开始的所有X.

    concatenations(s, set) =
      sum([[[x] + y for y in concatenations(s[len(x):], set - x))]
           for x in set if s.startswith(x)], [])
    

(代码是半蟒蛇,半数学;我希望这给出了足够的提示:p)

答案 1 :(得分:3)

一种可能性是将搜索结构化为生成器。在python中,它可能如下所示:

def concatenations(target_string, fragments, concat_path=()):
    if not target_string:
        yield concat_path
    else:
        for frag in fragments:
            if target_string.startswith(frag):
                new_target = target_string[len(frag):]
                new_path = concat_path + (frag,)
                for c in concatenations(new_target, fragments, new_path):
                    yield c

请注意,我假设集合中的元素可以在字符串中出现多次。如果这不合适,请在递归调用中将fragments替换为fragments - {frag}

您可以通过将生成器中的所有结果收集到列表中来获取所有元素:

fragments = {"ab", "cde", "abcd", "a", "bcd", "cd", "e"}
list(concatenations("abcde", fragments))

这会产生:

[('a', 'bcd', 'e'), ('abcd', 'e'), ('ab', 'cde'), ('ab', 'cd', 'e')]

随着搜索的进行,您还可以将所有结果累积到列表中。

答案 2 :(得分:0)

不使用树的方法是通过遍历所有可能的排列来尝试它,但是只要你对这种随机性添加任何智能,我就会觉得你会再次回到树状结构。 / p>

那就是说trie结构听起来很合适。有两种流行的Python实现可用于实现它,triePyTrie