简体   繁体   English

试图用 Python 实现自上而下的 DP,相信缓存不起作用

[英]Attempting to implement top down DP with Python, believe caching is not working

This is homework, but with the current lockdown, I'm unable to ask my tutor for help so I thought I'd as the internet :)这是家庭作业,但由于目前的封锁,我无法向我的导师寻求帮助,所以我想我会上网 :)

I am trying to implement specifically top-down (so caching) DP for a Longest Common Subsequence algorithm.我正在尝试为最长公共子序列算法专门实现自上而下(因此缓存)DP。 And here is what I have written:这是我写的:

def lcs(s1, s2, known=None):
    if(known == None):
        known = {}
    if len(s1) == 0:
        return 0
    if len(s2) == 0:
        return 0
    else:
        if((s1, s2) in known):
            return known[(s1, s2)]
        elif(s1[-1] == s2[-1]):
            now_known = (1 + lcs(s1[:-1], s2[:-1]))
            known[(s1, s2)] = now_known
            return now_known
        else:
            now_known = max((lcs(s1, s2[:-1])), (lcs(s1[:-1], s2)))
            known[(s1, s2)] = now_known
            return now_known

My understanding of what I have wrriten is:我对所写内容的理解是:

  • My code checks if either of the strings is empty, if that is the case, the longest common subsequence will be 0我的代码检查其中一个字符串是否为空,如果是这样,最长公共子序列将为 0
  • My code then checks if the two strings it is checking is in the cache, if it is, it returns the values associated with it in the cache.我的代码然后检查它正在检查的两个字符串是否在缓存中,如果是,则返回缓存中与其关联的值。
  • My code then checks if the last element in the two strings is the same, in which case, the longest subsequences will be 1 plus the lcs of the rest of the string.然后我的代码检查两个字符串中的最后一个元素是否相同,在这种情况下,最长的子序列将是 1 加上字符串其余部分的 lcs。
  • Otherwise, my code recursivly calls itself twice, once for each string minus its last element否则,我的代码递归调用自己两次,每个字符串减去它的最后一个元素一次

When the above code is run on two small strings:当上面的代码在两个小字符串上运行时:

s1 = "abcde"
s2 = "qbxxd"
lcs = lcs(s1, s2)
print(lcs)

I get the correct output of 2 :) However, when running on larger inputs, such as:我得到了正确的输出 2 :) 但是,在较大的输入上运行时,例如:

s1 = "Look at me, I can fly!"
s2 = "Look at that, it's a fly"
print(lcs(s1, s2))

My code times out.我的代码超时。 This, plus some print statement testing (testing what is added to "known" when I'm adding to the "known") leads me to believe I'm implementing my caching incorrectly.这一点,加上一些打印语句测试(当我添加到“已知”时测试添加到“已知”的内容)让我相信我没有正确地实现我的缓存。 This could be a simple silly bug fix problem, in which case I apologize, but I believe this to be an issue with my understanding of caching.这可能是一个简单愚蠢的错误修复问题,在这种情况下,我深表歉意,但我相信这是我对缓存理解的问题。 Also, I am aware of "lru cache" which does the caching for me, however for the purposes of this homework exercise, I'm required to write my own caching.另外,我知道“lru cache”为我做缓存,但是为了这个家庭作业的目的,我需要编写自己的缓存。

Any insight would be greatly appreciated.任何见解将不胜感激。

As comments pointed out, you do not pass known in on the recursive calls.正如评论所指出的,您不会在递归调用中传递known Therefore it always starts as None , then gets filled in with {} , and you never benefit from caching.因此它总是以None开头,然后用{}填充,并且您永远不会从缓存中受益。

I personally am fond of the following pattern我个人喜欢以下模式

def lcs(s1, s2):
    cache = {}

    def _lcs (i, j):
        if (i, j) not in cache:
            ... (logic here) ...

        return cache[(i, j)]

    return _lcs(0, 0)

The idea being that the cache and sequences are now created once, and you're just playing with indexes.这个想法是现在创建了一次缓存和序列,而您只是在使用索引。 I also don't forget to pass the cache around.我也不会忘记传递缓存。 :-) :-)

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

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