例:
A=['A','B','C','B','D','A','B']
B=['B','D','C','A','B','A']
最长公共子序列是BCBA或BDAB,子序列可以不是连续的,相对顺序一样就可以。
这是一道动态规划题,首先我们需要一个c[a+1][b+1]来记录状态,注意每一维需要比数组长1,为了保存当A,B为空时候的情况。然后我们从[0,0]开始按行填表。按如下公式进行填表
我们想象一下AB两个数组最后一个元素如果是相同的,那么它肯定在最长公共子序列里,那么问题就缩小为去掉最后一个元素找子序列的问题。如果最后一个元素不一样,这里就有分支了,我可以从A中去掉一个,也可以从B中去掉一个,最后我肯定是要选择收益最高的那个。
A=['A','B','C','B','D','A','B']
B=['B','D','C','A','B','A']
len_a = len(A)
len_b = len(B)
c=[[0 for i in range(len_b+1)]for j in range(len_a+1)]
for i in range(len_a):
for j in range(len_b):
if A[i] == B[j]:
c[i+1][j+1] = c[i][j] + 1
elif c[i+1][j] > c[i][j+1]:
c[i+1][j+1] = c[i+1][j]
else:
c[i+1][j+1] = c[i][j+1]
i=len_a
j=len_b
ans=[]
while i>0 and j>0:
if A[i-1]==B[j-1]:
ans.append(A[i-1])
i=i-1
j=j-1
else:
if c[i-1][j]>c[i][j-1]:
i=i-1
else:
j=j-1
print(ans)
#['B', 'A', 'D', 'B']
print (c[len_a][len_b])
#4
最后最长的长度在表中的右下角,现在只得到了长度,如果想获得具体的序列,还需要回溯。我们从右下角开始,如果A,B元素相同,那么这个元素就在序列里,同时它的状态是从[i-1][j-1]得来的,所以回溯到[i-1][j-1]。如果不相同,就看它是从哪个分支过来的,我们走较大的那个分支。如果两个分支是相等的,我们就选一个方向,注意回溯的时候处理相等的情况需要从始至终选定一个方向,最终回溯到i,j有一个是0为止。因为有相等的情况出现,所以最长子序列不一定唯一
参考
https://blog.csdn.net/someone_and_anyone/article/details/81044153
https://blog.csdn.net/littlethunder/article/details/25637173