最長公共子序列 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)