#最长公共子序列
# 思想:动态规划
# 条件:给定两个字符串,或者是列表 s1='ABCDBCED' s2='ADCBDCBABC'
# 最长公共子序列是最长的,但是不要求连续,与最长公共字串相区分
def LCS(s1,s2,result):
len1=len(s1)
len2=len(s2)
# 生成一个二维数组来存放当前最长公共子序列长度
for i in range (1,len1+1):
print("i:",i)
row0=result[i-1]
row1=result[i]#row1是结果数组中正在填充数据的那一行
s1i=s1[i-1]
for j in range(1,len2+1):# [1,7)
print("j:",j)
s2j=s2[j-1]
if(s2j==s1i):
row1[j]=row0[j-1]+1
else:
# 取左一个与上一个中较大者
row1[j]=max(row0[j],row1[j-1])
s1='ABCDBAB'
s2='BDCABA'
# s2 ---->
# |s1 B D C A B A
# |A
# |B
# C
# D
# B
# A
# B
result=[]
for i in range(len(s1)+1):
cols=[]
for j in range(len(s2)+1):
cols.append(0)
result.append(cols)
# result相当于是二维数组,行或者列为0,其值都为0,存放比较的结果
# result[i][j]的值表示s1的前i个字符构成的串s1i与 s2的前j个字符构成的串s2j的最长公共子序列长度
LCS(s1,s2,result)
#
for i in range (len(s1)+1):
print(result[i])
#result的最后一个元素值则是最长子序列长度
# 现在考虑如何输出最长公共子序列
lcs=[]
i=len(s1)+1
j=len(s2)+1
# 往左上方走
while i>1 and j>1:
if(s1[i-2]==s2[j-2]):
lcs.append(s1[i-2])
print(s1[i-2])
i-=1
j-=1
else:
rowi=result[i-1]#第i行记录的值
rowi_1=result[i-2]# 第i-1行记录的值
# 比较当前元素的左一个与左上元素的值的大小,哪边大朝哪个方向走
# 左元素大于左上,则向左走
if(rowi[j-2]>rowi_1[j-2]):
j-=1
else:
i-=1
#
print("lcs:",lcs[::-1])
# 存在的问题,只能求出一个最短子序列,但事实上还存在 BCBA