简体   繁体   English

由于递归,hackerrank密码破解程序超时

[英]hackerrank password cracker timeout due to recursion

This problem simply restated is this: given a bunch of strings and a target string, what all combinations from the given string can combine together to form target string with and without repetition. 简单地重申一下这个问题是这样的:给定一串字符串和一个目标字符串,给定字符串中的所有组合可以组合在一起而形成一个重复或不重复的目标字符串。

eg 例如

strings : we do what we must because we can 字符串 :我们做我们必须做的,因为我们可以

target : wedowhatwemustbecausewecan 目标 :因为我们可以

output : we do what we must because we can 输出 :我们做我们必须做的,因为我们可以

Approach I took is to remove every longer word from the target until target becomes empty. 我采取的方法是从目标中删除每个更长的单词,直到目标变空。 If targets becomes empty then just return the output. 如果目标变为空,则仅返回输出。 If longer words doesn't lead to a solution then try with shorter words and so on. 如果较长的单词不能解决问题,请尝试使用较短的单词,依此类推。 I am also using memoization to make sure that if the target is already tried then just return, same as backtracking with memoization. 我还使用备忘录来确保如果已经尝试了目标,那么只需返回就可以了,就像通过备忘录回溯一样。

This apporach passed all the testcases except 2, where I am getting timeout. 该方法通过了除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

Please help in providing a hint . 请帮助提供提示 Complete solution is here . 完整的解决方案在这里

You could try dynamic programming approach where you mark the ending locations of each password. 您可以尝试动态编程方法,在其中标记每个密码的结束位置。 Start by trying every password at the beginning of the longer string. 首先在长字符串的开头尝试每个密码。 If it fits there mark down the ending position in the longer string. 如果合适,在较长的字符串中标记结束位置。 You could then repeat the same process for every location in longer string where previous location is marked as ending position. 然后,您可以对较长字符串中的每个位置(以前的位置标记为结束位置)重复相同的过程。

Hope this helps you getting started, I've intentionally left out some of the information required for full solution so let me know in comments if you're still stuck. 希望这对您有所帮助,我故意遗漏了完整解决方案所需的一些信息,因此,如果您仍然遇到问题,请在评论中告诉我。

EDIT Here's a short example on what I'm talking about. 编辑这是我正在谈论的简短示例。 It doesn't allow you to reconstruct the solution but it shows how to do the matching without recursion: 它不允许您重构解决方案,但是它显示了如何进行匹配而无需递归:

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])

Output: 输出:

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

EDIT Took a closer look at the code provided in the question. 编辑仔细查看问题中提供的代码。 The issue is on the line where matched strings are filtered by the characters contained in the target: for char in paswd: . 问题在于,匹配的字符串由target:中包含的字符过滤( for char in paswd: Instead of doing filtering for every character in the target string the filtering should be done for every unique character: for char in set(paswd): . 代替对目标字符串中的每个字符进行过滤,应该对每个唯一字符进行过滤: for char in set(paswd): Fix that and solution runs much faster but would probably be even faster if there wouldn't be that kind of filtering at all since the maximum number of shorter strings is 10. 解决此问题,解决方案的运行速度要快得多,但如果根本不进行这种过滤,则可能会更快,因为较短的字符串的最大数量为10。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM