最長公共子串行(Lcs)

2021-08-26 05:22:52 字數 2646 閱讀 5931

問題描述

子串行:與原序列順序相關的乙個原序列的乙個子集

例如:abcscy 的乙個子串行  bsy

公共子串行即兩個序列共有的一段子串行,例如abcscy和abfsgp都有bsy序列

所以最長公共子串行即是兩端字串的公共子串行最長的一段

問題求解

1.暴力法

這裡涉及到排列組合,與字串的長度呈指數相關

2.動態規劃

2.1找子問題,考慮兩條子串行的最後一位

設a= a1,a2,a3,a4...ax b = b1,b2,b3,...by 求最長公共子串行lcs(x,y)=z=z1,z2....zm;z的長度計為lcs(x,y)

(1)ax = by

假設ax和by的最後一位 ax=by=t , 則 z的最後一位lcs(x,y)=zm=t

證明:(反證法)lcs(x,y)的最後一位為aa=bb不為t,且a所以zm=t

有了zm=t 就可以得到 當ax = by時 有 lcs(x,y) = lcs(x-1,y-1)+1

(2)ax≠by

這裡設lcs(x,y)的最後一位為t

(2.1)t≠ax,有lcs(x,y)=lcs(x-1,y)

(2.2)t≠by,有lcs(x,y)=lcs(x,y-1)

由於兩種情況都可能發生 所以根據最長公共子串行的定義 lcs(x,y)=max(lcs(x-1,y),lcs(x,y-1))

(3)當ax或by為空序列的時候lcs(x,y)=0

所以得到以下遞推關係式

lcs(x,y) =

(1)lcsx-1,y-1)+1(ax=by=t)

(2)max(lcs(x-1,y),lcs(x,y-1))(t≠ax,t≠by)

(3)0 ax或by為空

找到了遞推關係式,就有了兩種想法:①利用遞推關係式遞迴,從後往前退②利用動態規劃,從前往後推,這裡由於遞推關係式中存在過多的重疊子問題例如:lcs(x-1,y)中就包括lcs(x-1,y-1)在求解的時候就會多次重複求解,造成時間複雜度提高,所以這裡選擇使用動態規劃從前往後推,將子問題的解儲存到陣列中備用,從而降低時間複雜度

由上面的遞推關係式很容易就會想到用乙個二維陣列c[m][n]存子問題的結果

以下是陣列的遞推表示式

由這個二維陣列可以很容易得到最長公共子串行的長度,但如何得到最長功能公共子串行本身呢?

通過回溯二維陣列,以下面這張圖為例,我們可以很容易看到二維陣列的求解過程

當發生ax=by=t時即圖中斜箭頭地方,記錄發生位置列印字元,遍歷完陣列的時候,最長公共子串行也就列印完了、

分析到此,上**

#最長公共子串行,動態規劃

a='abcbdab'

b='bdcaba'

m=len(a)

n=len(b)

c=[[0 for i in range(n+1)] for j in range(m+1)] #列表生成表示式,生成乙個n行m列的二維陣列

d=[[-1 for i in range(n+1)] for j in range(m+1)]

#得到最長公共子陣列的長度陣列c和記錄相同字元出現的位置

def len_lcs(a,b,c,d):

for i in range(1,len(a)+1):

for j in range(1,len(b)+1):

if a[i-1]==b[j-1]:

c[i][j]=c[i-1][j-1]+1

d[i][j]=0

elif c[i-1][j] >= c[i][j-1]: #當不相等時

c[i][j] = c[i-1][j]

d[i][j] = 1

else:

c[i][j] = c[i][j-1]

d[i][j] = 2

return c[len(a)][len(b)]

lcs_ab = len_lcs(a,b,c,d)

print('最長公共子串行長度:%d'%(lcs_ab))

print('最長公共子串行:',end='')

#根據陣列d求出最長公共子串行

def print_lcs(a,d,x,y):

if x==0 or y==0:

return

elif d[x][y] == 0 :

print_lcs(a,d,x-1,y-1)

print(a[x-1],end='')

elif d[x][y] == 1:

print_lcs(a,d,x-1,y)

else:

print_lcs(a,d,x,y-1)

print_lcs(a,d,m,n)

思考:

上述**的時空間複雜度如何分析

空間複雜度

**使用了乙個(m+1)*(n+1)的二維陣列,所以可以認為**的空間複雜度為o(m*n)

最長公共子串行一般不唯一

如果只需要求最長公共子串行的長度,有什麼辦法可以簡化**

最長公共子串行有什麼應用

LCS 最長公共子串行

問題描述 我們稱序列z z1,z2,zk 是序列x x1,x2,xm 的子串行當且僅當存在嚴格上 公升的序列 i1,i2,ik 使得對 j 1,2,k,有 xij zj。比如z a,b,f,c 是 x a,b,c,f,b,c 的子串行。現在給出兩個序列 x和 y,你的任務是找到 x和 y的最大公共子...

LCS最長公共子串行

求兩個字串的最大公共子串行問題 子串行的定義 若給定序列x 則另一串行z 是x的子串行是指存在乙個嚴格遞增下標序列使得對於所有j 1,2,k有 zj xij。例如,序列z 是序列x 的子序列,相應的遞增下標序列為。分析 用動態規劃做 1.最長公共子串行的結構 事實上,最長公共子串行問題具有最優子結構...

LCS最長公共子串行

lcs是longest common subsequence的縮寫,即最長公共子串行。乙個序列,如果是兩個或多個已知序列的子串行,且是所有子串行中最長的,則為最長公共子串行。複雜度對於一般的lcs問題,都屬於np問題。當數列的量為一定的時,都可以採用動態規劃去解決。解法動態規劃的乙個計算最長公共子串...