1.問題描述
輸入:x = (x1,x2,...,xn) , y = (y1,y2, ... ,ym)
輸出:z = (z1,z2, ... , zk)為x與y的最長公共子串行
2.演算法分析
一般用動態規劃求解,最重要的就是抓住問題特點來優化子結構。現在分析該問題的特點:如果xn與ym字元相同,那麼lcs_xnym的解就等於lcs_xn-1ym-1的解加上xn(或者ym);如果xn與ym字元不同,那麼lcs_xnym的解可在lcs_xn-1ym和lcs_xnym-1兩者之間求最大值。
初始化問題,只需要將lcs_x0yj ( j=0,1, ... , m) 、 lcs_xiy0 ( i=0,1, ... , n)設定為0即可。
3.演算法實現
import numpy as np
str_x = np.array(list('abcbdab')) # 字串x
str_y = np.array(list('bdcaba')) # 字串y
num_x = len(str_x) # 字串x的長度
num_y = len(str_y)# 自動糊穿y的長度
lcs = np.zeros( (num_x + 1) * (num_y + 1) ).reshape(num_x+1, -1) #存放lcs解,即最長公共子串行的長度
location = np.zeros( (num_x + 1) * (num_y + 1) ).reshape(num_x+1, -1) #存放位置,1表示斜上方,2表示左邊,3表示上邊
'''由於lcs利用0矩陣構造因此不需要初始化,直接遞推優化的子結構即可求解'''
i = 1
j = 1
while i <= num_x:
j = 1
while j<= num_y:
if str_x[i-1] == str_y[j-1]:
lcs[i][j] = lcs[i-1][j-1] + 1
location[i][j] = 1
else:
if lcs[i-1][j] >= lcs[i][j-1]:
lcs[i][j] = lcs[i-1][j]
location[i][j] = 3
else:
lcs[i][j] = lcs[i][j-1]
location[i][j] = 2
j += 1
i += 1
print 'x和y的最大公共子串行的長度為:',lcs[num_x][num_y]
# 定義遞迴程式輸出公共子串行
def print_substr(str_x, loc, i, j):
if i <= 0 | j <= 0:
return
if loc[i][j] == 1:
print str_x[i-1],
print_substr(str_x, loc, i-1, j-1)
elif loc[i][j] == 2:
print_substr(str_x, loc, i, j-1)
else:
print_substr(str_x, loc, i-1, j)
print 'x和y的最大公共子串行為:',print_substr(str_x, location, num_x, num_y)
4.時間複雜性
-總時間複雜性為o(m*n).
5.空間複雜性
使用lcs陣列和location陣列,需要空間o(m*n)。
動態規劃之最長公共子串行(lcs)
最長公共子串行的定義是,乙個數列z分別是已知數列的子串行 子串行不一定是連續序列,是在該序列中刪去若干元素後得到的序列 且是所有符合此條件序列中最長的,則z成為最長公共子串行lcs longest common subsequences 有些地方則說公共子串就是要求連續的子串行,有些地方則不是,這裡...
動態規劃之 最長公共子串行 LCS
這個問題是動態規劃演算法中的乙個經典問題,先看問題描述 lcs 兩個字串 x和 y,找到他們最長的公共子串行,該序列不要求是連續的。公共子串行的意思就是序列的相對順序是不變的,但是序列不一定是連續的。例如 x bdcaba y abcbdab 他們的最長公共子串行是bcba和bdab,長度都為4,找...
動態規劃之最長公共子串行(LCS)
動態規劃之最長公共子串行問題 前言 乙個給定序列的子串行,就是將給定的序列中零個或多個元素去掉後得到的結果。其形式化定義如下 給定乙個序列x 另乙個序列z 滿足如下條件時稱為x的子串行,即存在乙個嚴格遞增的x下表序列 i1,i2 ik 對所有j 1,2,3,k滿足xi zj例如z 是x 的子串行對應...