如何编写使用动态编程查找最长公共子序列的函数?

时间:2020-04-01 22:46:17

标签: python python-3.x longest-substring

为了清楚起见,我正在寻找子序列本身,而不是长度。我已经编写了大部分时间都可以使用的函数,但在某些情况下不起作用。我必须递归地编写此代码,而没有任何循环或导入。我使用了备忘录功能来提高效率,但此处未包括该功能。

当s1 =“ abcde”和s2 =“ qbxxd”(正确返回“ bd”)时,此功能有效,但在s1 =“看着我,我会飞!”时,此功能无效和s2 =“看那是一只苍蝇”,应该返回“看,一只苍蝇”,但我却改为“看一只苍蝇”。无论出于何种原因,逗号和空格都会被忽略。我已经尝试过s1 =“ ab,cde”和s2 =“ qbxx,d”正确返回“ b,d”。

def lcs(s1, s2):
"""y5tgr"""
i = len(s1)
j = len(s2)
if i == 0 or j == 0:
    return ""
if s1[i-1] == s2[j-1]:
    return lcs(s1[:-1], s2[:-1]) + s1[i-1]
else:
    return max(lcs(s1[:-1], s2), lcs(s1, s2[:-1]))

我觉得问题在于最后一行和max函数。我见过for和while循环的解决方案,但并非没有。

2 个答案:

答案 0 :(得分:1)

只需稍作改动即可修复您的代码(没错,问题出在最大)。

只需更改max即可使用其键函数找到最大长度的字符串

def lcs(s1, s2):
    """y5tgr"""
    i = len(s1)
    j = len(s2)
    if i == 0 or j == 0:
        return ""
    if s1[i-1] == s2[j-1]:
        return lcs(s1[:-1], s2[:-1]) + s1[i-1]
    else:
        # Find max based upon the string length
        return max(lcs(s1[:-1], s2), lcs(s1, s2[:-1]), key=len)

但是,这很慢,没有备忘录

具有记忆功能的代码(以提高性能)

Memoization Decorator Reference

import functools

def memoize(obj):
    cache = obj.cache = {}

    @functools.wraps(obj)
    def memoizer(*args, **kwargs):
        if args not in cache:
            cache[args] = obj(*args, **kwargs)
        return cache[args]
    return memoizer

@memoize
def lcs(s1, s2):
    """y5tgr"""
    i = len(s1)
    j = len(s2)
    if i == 0 or j == 0:
        return ""
    if s1[i-1] == s2[j-1]:
        return lcs(s1[:-1], s2[:-1]) + s1[i-1]
    else:
        return max(lcs(s1[:-1], s2), lcs(s1, s2[:-1]), key=len)

测试

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

输出

Look at ,  a fly

答案 1 :(得分:0)

对于字符串,max采用按字典顺序倒数第二个字符串:

>>> max("a", "b")
'b'
>>> max("aaaaa", "b")
'b'
>>> 

当然不是您需要的;您似乎要寻找两者中的 longer 。 您不需要循环,只需进行比较即可:

lsc1 = lcs(s1[:-1], s2)
lcs2 = lcs(s1, s2[:-1])
return lcs1 if len(lcs1) > len(lcs2) else lcs2