由于递归而导致hackerrank密码破解程序超时

时间:2017-08-27 05:44:51

标签: python algorithm recursion backtracking memoization

This problem简单地重申:给定一串字符串和一个目标字符串,来自给定字符串的所有组合可以组合在一起形成具有和不重复的目标字符串。

e.g。

字符串:我们会做我们必须做的事情,因为我们可以

目标:wedowhatwemustbecausewecan

输出:我们必须做,因为我们可以

我采取的方法是从目标中删除每个较长的单词,直到目标变空。如果目标变空,则只返回输出。如果较长的单词没有导致解决方案,那么尝试使用较短的单词等等。我也在使用memoization来确保如果已经尝试了目标,那么只需返回,就像回溯与memoization一样。

这个apporach通过了所有的测试用例,除了2,我正在超时。

def recursions(word_map, paswd, output, remember):
    flag = 0
    if len(paswd) == 0:
        return 1
    if paswd in remember:
        return flag
    for char in paswd:
        for word in (word_map[char] if char in word_map else []):
            if paswd.startswith(word):
                output.append(word + " ")
                if recursions(word_map, paswd[len(word):], output, remember):
                    return 1
                output.pop()
        remember[paswd] = 1
    return flag

请提供提示。完整的解决方案是here

1 个答案:

答案 0 :(得分:1)

您可以尝试使用动态编程方法来标记每个密码的结束位置。首先尝试在较长字符串开头的每个密码。如果它适合,那么在较长的字符串中标记结束位置。然后,您可以对较长字符串中的每个位置重复相同的过程,其中前一个位置被标记为结束位置。

希望这可以帮助您入门,我故意遗漏了完整解决方案所需的一些信息,如果您仍然卡住,请在评论中告诉我。

编辑以下是我所谈论的一个简短示例。它不允许您重建解决方案,但它显示了如何在没有递归的情况下进行匹配:

passwords = ['foo', 'bar']
login = 'foobar'

ends_here = [False] * len(login)

for i in range(len(ends_here)):

    # Match password at the beginning or if password match
    # ended to previous index
    if i == 0 or ends_here[i - 1]:
        for pw in passwords:
            if login.find(pw, i, i + len(pw)) != -1:
                ends_here[i + len(pw) - 1] = True

print(ends_here)
print('We can match whole login attempt:', ends_here[-1])

输出:

[False, False, True, False, False, True]
We can match whole login attempt: True

编辑仔细查看问题中提供的代码。问题在于匹配的字符串被目标中包含的字符过滤:for char in paswd:。不应对目标字符串中的每个字符进行过滤,而应对每个唯一字符进行过滤:for char in set(paswd):。修复它和解决方案运行得更快但如果根本没有那种过滤可能会更快,因为最短的字符串数是10。