最长公共子序列 LCS:
动态规划法得出以下:
LCS(Xm,Yn) = LCS(Xm-1,Yn-1)+1 ## xm=yn
LCS(Xm,Yn) = MAX{LCS(Xm-1,Yn),LCS(Xm,Yn-1)} ## xm!=yn
代码有如下两种方式实现:
1. 递归算法
递归算法实现,重点在于把它看成一颗二叉树,进行的分解算法。然而递归算法计算重复度太高。
#!/usr/bin/env python
# -*- coding:utf-8 -*-
def LCS(str_x, coord_x, str_y, coord_y):
"""
# 递归算法实现,重点在于把它看成一颗二叉树,进行的分解算法。然而递归算法计算重复度太高。
:param str_x:
:param coord_x: 初始值应传入 len(str_x) - 1
:param str_y:
:param coord_y: 初始值应传入 len(str_y) - 1
:return:
"""
if coord_x < 0 or coord_y < 0:
return ""
if str_x[coord_x] == str_y[coord_y]:
return LCS(str_x, coord_x-1, str_y, coord_y-1) + str_x[coord_x]
else:
sub_node_left = LCS(str_x, coord_x-1, str_y, coord_y)
sub_node_right = LCS(str_x, coord_x, str_y, coord_y-1)
if len(sub_node_left) > len(sub_node_right):
return sub_node_left
else:
return sub_node_right
if __name__ == "__main__":
# strX = "BDCABA"
# strY = "ABCBDAB"
strX = "abcicba"
strY = "abdkscab"
print (LCS(strX, len(strX)-1, strY, len(strY)-1))
2. 二维数组备忘法 (与动态规划法是两回事)
#!/usr/bin/env python
# -*- coding:utf-8 -*-
#strX = "BDCABA"
#strY = "ABCBDAB"
strX = "abcicba"
strY = "abdkscab"
def produceLcsXY(s_x, s_y):
"""
# LCS 二维数组备忘记法
:param s_x:
:param s_y:
:return:
"""
len_x = len(s_x)
len_y = len(s_y)
print("初始化 %s*%s 的二维数组" %(len_x,len_y))
storeXY = [[0 for i in range(len_x+1)] for j in range(len_y+1)]
#print(storeXY)
for y in range(1, len_y+1):
for x in range(1, len_x+1):
if strX[x-1] == strY[y-1]:
storeXY[y][x] = storeXY[y-1][x-1] + 1
else:
storeXY[y][x] = max(storeXY[y-1][x], storeXY[y][x-1])
print("生成 字符串:%s 和 字符串 %s 的LCS备忘记法" % (s_x, s_y))
return storeXY
def getLCS(storeXY, s_x, s_y):
"""
# LCS回溯法取值
:param storeXY:
:param s_x:
:param s_y:
:return:
"""
len_x = len(storeXY[0])
len_y = len(storeXY)
LCS_string = ""
x, y = len_x - 1, len_y - 1
while True:
if storeXY[y][x] == 0:
break
if s_x[x-1] == s_y[y-1]:
LCS_string = s_x[x-1] + LCS_string
x, y = x-1, y-1
else:
if storeXY[y][x-1] > storeXY[y-1][x]:
x, y = x - 1, y
else: # storeXY[y - 1][x] >= storeXY[y][x - 1]:
x, y = x, y - 1
print("最长公共子序列为:%s" %LCS_string)
return LCS_string
if __name__ == "__main__":
storeXY = produceLcsXY(strX, strY)
for item in storeXY:
print (item)
print(getLCS(storeXY, strX, strY))
实践:求两字符串的相似度
c : 最长公共子串序列
m:字符1长度
n:字符2长度
相似度 = 2 * c / (m + n)