我正在使用动态编程解决LCS问题。在没有查看解决方案的情况下,我自己无法获得DP解决方案。
我目前的理由是给出两个字符串,P和Q:
2^n
。2^m
。因此,如果我们要检查共享子序列,则运行时间为O(2^n * 2^m)
或O(2^(n+m))
。
我不明白我们如何从这种强力解决方案转变为动态编程解决方案。推导子解决方案表的逻辑是什么?
我不知道如何从这一点直接跳到DP的子解决方案表。这样做的逻辑是什么?
我知道我们需要识别重叠的子解决方案。但是我无法找到一个很好的解释来识别它然后进入子解决方案表。
如果这个问题有意义,请告诉我。
答案 0 :(得分:0)
这是为这种算法创造魔力的基本思想。
考虑2个字符串S1
和S2
,
S1 = c1,c2,c3,........cm, length = m
和
S2 = b1,b2,b3,........bn, length = n
假设你有一个函数LCS(arg1,arg2)
,其中
arg1 = S1,m , string S1 of length of m
和
arg2 = S2,n,长度为n的字符串S2
和LCS(arg1,arg2)
将为我们提供2个参数的最长公共子序列的长度。
现在假设两个字符串的最后一个字符相同。
bn = cm
假设没有其他两个字符相同。这意味着:
LCS(arg1,arg2) = 1(last character) + 0(remaining strings)
现在,如果你已经理解了上面的等式,那么很明显,如果没有其他两个字符匹配,我们确实有匹配的东西(在剩余的字符串中),那么:
LCS(arg1,arg2) = 1(last character) + LCS(arg1 - cm,arg2 - bn)(Remaining strings)
但如果最后两个字符不匹配,那么肯定我们必须考虑每个字符串中的倒数第二个字符,这就是为什么我们在< strong>最后2个字符不匹配:
LCS(arg1,arg2) = max(LCS(arg1 - cm,arg2) , LCS(arg1 ,arg2 - bn))