動態規劃之最長公共子串行(LCS)問題

2021-08-08 22:21:39 字數 1784 閱讀 6510

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 的子串行對應...