Algorithm 打印最长的公共序列

Algorithm 打印最长的公共序列,algorithm,python,data-structures,Algorithm,Python,Data Structures,我试图实现经典问题的解决方案,但我感到困惑,因为我得到了一些我没有找到好结果的案例 输出:“最长公共序列”、“长度” 对于第一种情况: x= "AGGTAB" y= "GXTXAYB" print longestCommonSeq(x,y) 结果:('GTAB',4) 这是对的 但对于类似的情况: a= "APBCADCQER" b= "RASBTAUCVE" print longestCommonSeq(a,b) ('', 5) 我错过了什么?谁能给我一个提示吗?你把桌子造错了;您应

我试图实现经典问题的解决方案,但我感到困惑,因为我得到了一些我没有找到好结果的案例

输出:“最长公共序列”、“长度”

对于第一种情况:

x= "AGGTAB"
y= "GXTXAYB"
print longestCommonSeq(x,y)
结果:
('GTAB',4)
这是对的

但对于类似的情况:

a= "APBCADCQER" 
b= "RASBTAUCVE"
print longestCommonSeq(a,b)

 ('', 5)

我错过了什么?谁能给我一个提示吗?

你把桌子造错了;您应该将行保留在
i=0
处,将列保留在
j=0
处,并将匹配项放在较高的行中。这意味着您需要将1添加到第一个循环中的
i
j
坐标中,因为Python从0开始索引

因此,您将得到一个末尾为0的表;使用类似于的符号,您基本上可以构建以下内容:

┌─┬─────┬─────────┬─────────┬─────┬──────┬───────┬─┐
│ │A    │G        │G        │T    │A     │B      │ │
├─┼─────┼─────────┼─────────┼─────┼──────┼───────┼─┤
│G│< ^ 0│\ G      │\ G      │< G  │< G   │< G    │0│
├─┼─────┼─────────┼─────────┼─────┼──────┼───────┼─┤
│X│< ^ 0│^ G      │< ^ G    │< ^ G│< ^ G │< ^ G  │0│
├─┼─────┼─────────┼─────────┼─────┼──────┼───────┼─┤
│T│< ^ 0│^ G      │< ^ G    │\ GT │< GT  │< GT   │0│
├─┼─────┼─────────┼─────────┼─────┼──────┼───────┼─┤
│X│< ^ 0│^ G      │< ^ G    │^ GT │< ^ GT│< ^ GT │0│
├─┼─────┼─────────┼─────────┼─────┼──────┼───────┼─┤
│A│\ A  │< ^ A | G│< ^ A | G│^ GT │\ GTA │< GTA  │0│
├─┼─────┼─────────┼─────────┼─────┼──────┼───────┼─┤
│I│^ A  │< ^ A | G│< ^ A | G│^ GT │^ GTA │< ^ GTA│0│
├─┼─────┼─────────┼─────────┼─────┼──────┼───────┼─┤
│B│^ A  │< ^ A | G│< ^ A | G│^ GT │^ GTA │\ GTAB │0│
├─┼─────┼─────────┼─────────┼─────┼──────┼───────┼─┤
│ │0    │0        │0        │0    │0     │0      │0│
└─┴─────┴─────────┴─────────┴─────┴──────┴───────┴─┘

< and ^: maximum picked
\: add matching character to cell to the top left.
接下来,您不需要在第二个循环中查阅
x
y
,只查阅
LCS
表。因为最后一行和最后一列总是以
0
结束,所以当
x
y
的最后一个字符不匹配时,算法的版本会平缓下来,而当您没有命中表中列出的LCS路径时,您只会几乎随机地递减
i
j

请注意,前两个
for
循环是完全冗余的,可以删除;整个
LCS
表只包含
0
值,为什么要将它们设置为
0
更多?Wikipedia中的伪代码使用从1到长度(包含)的循环,但是由于Python从0开始,您向长度添加1以保持长度包含,因此不需要在此处执行此操作

更正后的函数如下所示:

def longestCommonSeq(x,y):
    LCS = [[0 for z in range(len(y) + 1)] for z in range(len(x) + 1)] 
    for i in range(len(x)):
        for j in range(len(y)):
            if x[i] ==  y[j]:
                LCS[i + 1][j + 1] = 1 + LCS[i][j]
            else: 
                LCS[i + 1][j + 1] = max(LCS[i][j + 1], LCS[i + 1][j])

    res = ''
    i, j = len(x), len(y)

    while i and j:
        if LCS[i][j] == LCS[i-1][j]:
            i -= 1
        elif LCS[i][j] == LCS[i][j-1]: 
            j -= 1
        else:
            res = x[i-1] + res
            i -= 1
            j -= 1

    return res, LCS[-1][-1]
由于
LCS
表现在已正确构建,因此我们也可以使用
LCS[-1][1]
作为最大长度值

这将产生预期的结果:

>>> x = "AGGTAB"
>>> y = "GXTXAYB"
>>> print longestCommonSeq(x, y)
('GTAB', 4)
>>> a = "APBCADCQER" 
>>> b = "RASBTAUCVE"
>>> print longestCommonSeq(a, b)
('ABACE', 5)
另一种方法是,在第二阶段将off设置为1,然后查看与输入字实际对应的LCS表格单元格;e、 g.从
i
j
中减去1:

def longestCommonSeq(x,y):
    LCS = [[0 for z in range(len(y)+1)] for z in  range(len(x)+1)] 

    for i in range(len(x)):
        for j in range(len(y)):
            if x[i] ==  y[j]:
                LCS[i][j] = 1 + LCS[i - 1][j - 1]
            else: 
                LCS[i][j] = max(LCS[i - 1][j], LCS[i][j - 1])

    i, j = len(x) - 1, len(y) - 1
    print LCS

    res = "" 
    while i >= 0 and j >= 0:
        if x[i] == y[j]:
            res= x[i] + res
            i -= 1
            j -= 1 
        else:
            if LCS[i - 1][j] > LCS[i][j - 1]:
                i -= 1
            else: 
                j -= 1

    return res, LCS[len(x) - 1][len(y) - 1]
现在
i
j
的范围分别为
len(x)-1
0
len(y)-1
0
,您再次引用了正确的单元格

>>> x = "AGGTAB"
>>> y = "GXTXAYB"
>>> print longestCommonSeq(x, y)
('GTAB', 4)
>>> a = "APBCADCQER" 
>>> b = "RASBTAUCVE"
>>> print longestCommonSeq(a, b)
('ABACE', 5)
def longestCommonSeq(x,y):
    LCS = [[0 for z in range(len(y)+1)] for z in  range(len(x)+1)] 

    for i in range(len(x)):
        for j in range(len(y)):
            if x[i] ==  y[j]:
                LCS[i][j] = 1 + LCS[i - 1][j - 1]
            else: 
                LCS[i][j] = max(LCS[i - 1][j], LCS[i][j - 1])

    i, j = len(x) - 1, len(y) - 1
    print LCS

    res = "" 
    while i >= 0 and j >= 0:
        if x[i] == y[j]:
            res= x[i] + res
            i -= 1
            j -= 1 
        else:
            if LCS[i - 1][j] > LCS[i][j - 1]:
                i -= 1
            else: 
                j -= 1

    return res, LCS[len(x) - 1][len(y) - 1]