問題描述
子串行:與原序列順序相關的乙個原序列的乙個子集
例如: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問題。當數列的量為一定的時,都可以採用動態規劃去解決。解法動態規劃的乙個計算最長公共子串...