最长公共子序列的问题常用于解决字符串的相似度,是一个非常实用的算法,作为码农,此算法是我们的必备基本功。
举个例子,cnblogs这个字符串中子序列有多少个呢?很显然有27个,比如其中的cb,cgs等等都是其子序列,我们可以看出子序列不见得一定是连续的,连续的那是子串。
我想大家已经了解了子序列的概念,那现在可以延伸到两个字符串了,那么大家能够看出:cnblogs和belong的公共子序列吗?
在你找出的公共子序列中,你能找出最长的公共子序列吗?
从图中我们看到了最长公共子序列为blog,仔细想想我们可以发现其实最长公共子序列的个数不是唯一的,可能会有两个以上,
但是长度一定是唯一的,比如这里的最长公共子序列的长度为4。
需要O(N)的时间,总共也就是O(N*2**N),可以看出,时间复杂度为指数级,恐怖的令人窒息。
设一个C[i,j]: 保存Xi与Yj的LCS的长度。
递推方程为:
# 采用矩阵实现
def maxTwoArraySameOrderMethod(strA,strB):
resultlist=[]
a=len(strA)
b=len(strB)
# for i in range(0,a+1):
# resultlist.append([])
# for j in range(0,b+1):
# resultlist[i].append(0)
resultlist=[[0]*(b+1) for i in range(a+1)]
for i in range(1,a+1):
for j in range(1,b+1):
if strA[i-1] == strB[j-1]:
resultlist[i][j]=resultlist[i-1][j-1]+1
else:
resultlist[i][j]=max(resultlist[i][j-1],resultlist[i-1][j])
return resultlist[a][b]
#递归实现
def diguimaxTwoArraySameOrderMethod(strA,strB):
def dp(a,b):
if a == -1 or b == -1:
return 0
if strA[a] == strB[b]:
return dp(a-1,b-1)+1
else:
return max(dp(a-1,b),dp(a,b-1))
return dp(len(strA)-1,len(strB)-1)
print(maxTwoArraySameOrderMethod('cnblogs','belong'))
时间复杂度:构建矩阵我们花费了O(MN)的时间,回溯时我们花费了O(M+N)的时间,两者相加最终我们花费了O(MN)的时间。
空间复杂度:构建矩阵我们花费了O(MN)的空间,标记函数也花费了O(MN)的空间,两者相加最终我们花费了O(MN)的空间。