参考这个博客最长公共子序列(LCS)问题,写出了C++版的找出所有最大公共子序列的代码,然后我需要将这个代码用python实现一个,按照C++的逻辑,写出来后,但是最终的结果死活不正确,最后发现问题在于:递归过程中,递归变量在python中仅有一份,递归分支不能很好的保持过程中的状态量,需要对象的深拷贝。
#coding=utf8
#python3.5
import copy
MAX=10
len1=0
len2=0
# tag=[[0]*MAX]*MAX #这样得到的是浅拷贝:http://www.cnblogs.com/alibai/p/4027324.html
tag=[[0]*MAX for var in range(0,MAX)]
word_list1=[]
word_list2=[]
result=[]
def lcs_word(str1,str2):
global len1,len2,word_list1,word_list2,tag
word_list1=[var for var in str1.strip().split(" ") if var]
word_list2=[var for var in str2.strip().split(" ") if var]
if len(word_list1)>MAX-1:
word_list1=word_list1[:MAX-1]
if len(word_list2)>MAX-1:
word_list2=word_list2[:MAX-1]
len1=len(word_list1)
len2=len(word_list2)
for i in range(1,len1+1):
for j in range(1,len2+1):
if word_list1[i-1] == word_list2[j-1]:
tag[i][j]=tag[i-1][j-1]+1
else:
tag[i][j]=max(tag[i-1][j],tag[i][j-1])
def output_all(clen1,clen2,cresult):
global result
if clen1==0 or clen2==0:
# print(cresult[-1][::-1])
result=cresult
cresult.append([])
return
if word_list1[clen1-1]==word_list2[clen2-1]:
cresult[-1].append(word_list1[clen1-1])
output_all(clen1-1,clen2-1,cresult)
else:
if tag[clen1-1][clen2]>tag[clen1][clen2-1]:
output_all(clen1-1,clen2,cresult)
elif tag[clen1-1][clen2]<tag[clen1][clen2-1]:
output_all(clen1,clen2-1,cresult)
else:
# output_all(clen1-1,clen2,cresult)
# output_all(clen1,clen2-1,cresult) #全局空间只有一份cresult,所以这样写不行,需要拷贝出来一个副本!
#用上述的代码,输出的结果为:[['A', 'B', 'C', 'B'], ['B', 'A', 'C', 'B'], ['D', 'B'], []]
temp_cresult=copy.deepcopy(cresult[-1]) #深拷贝,保存最后一个元素
output_all(clen1-1,clen2,cresult)
cresult[-1]=temp_cresult
output_all(clen1,clen2-1,cresult)
#真正需要的结果为:[['A', 'B', 'C', 'B'], ['B', 'A', 'C', 'B'], ['B', 'A', 'D', 'B'], []]
lcs_word("A B C B D A B","B D C A B A")
# print(len1,len2)
# [print(var[:len2+1]) for var in tag[:len1+1]]
# print(word_list1)
# print(word_list2)
# print("test")
output_all(len1,len2,[[]])
print(result[:-1])
还有两个问题:
1. 需要去重。
2. 输出函数的最初搜索点并不一定必须是tag[clen1][clen2],可以优化一下。