最長公共子串行及Python實現

2021-06-22 05:27:14 字數 3289 閱讀 1813

乙個給定序列的子串行是在該序列中刪除若干元素後得到的序列,確切的說,若給定序列x = ,則另乙個序列,y= ,當另乙個序列即是x的子串行又是y的子串行時,稱z是序列x也y的公共子串行。最長公共子串行問題為給定序列x和y,找到所有公共子串行中最長的乙個(非連續)。

解最長公共子串行問題的最容易想到的方法是窮舉法,即對x的所有子串行,檢查它是否也是y 的子串行,從而確定它是否為x和y 的公共子串行,並且在檢查過程中記錄最長的公共子串行。x的所有子串行檢查過後即可求出x和y 的最長公共子串行。x的沒個子序列相應於下標集的乙個子集。因此,公有2**m個不同的子串行,從而窮舉法需要指數時間。

事實上,最長公共子串行問題具有最優子結構性質:

設序列x=和y= 的乙個最長公共子串行為z=,則

(1) 若xm=yn ,則zk=xm=yn,且zk-1是xm-1和yn-1的最長公共子串行。

(2)若xm≠yn,且zk≠xm,則z是xm-1和y的最長公共子串行。

(3)若xm≠yn且zk≠yn,則z是x和yn-1的最長公共子串行。

證明略由最長公共子串行問題的最優子結構性質可知,要找出x=和y=的最長公共子串行,可以按照以下方式遞迴的進行:當xm=yn時,找出xm-1和yn-1的最長公共子串行,然後在其尾部加上xm(=yn)即可得到x和y的乙個最長公共子串行,當xm≠yn時,必須接兩個字問題,也就是要找出xm-1和yn的乙個最長公共子串行已經xm和yn-1的乙個最長公共子串行。並求兩個子問題公共子串行最長的。用c[i][j]記錄序列的xi和yj的最長公共子串行的長度,其中xi=;yj=,當i=0或j=0時,空序列是xi和yj的最長公共子串行故此時c[i][j]=0,由最優子結構性質可建立遞迴關係如下:

直接利用遞迴關係式容易寫出乙個計算c[i][j]的遞迴演算法,但其計算時間是隨輸入長度指數增長的,由於在考慮的子問題空間中,總共有φ(mn)個不同的子問題,因此,用動態規劃演算法由底向上計算最優值能提高演算法的效率。

計算最長公共子串行長度的動態規劃演算法lcslength以序列x=和y=最為輸入,暑促兩個陣列c和b,其中c[i][j]儲存xi和yj的最長公共子串行的的長度,b[i][j]記錄c[i][j]的值是由哪乙個子問題解決得到的。具體**實現如下(python)

def lcslength(m, n, x=none, y=none,c=none, b=none):

for i in range(1, m):

for j in range(1, n):

if x[i-1] == y[j-1]:

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

b[i][j] = 'equals'

elif c[i-1][j] >= c[i][j-1]:

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

b[i][j] = 'up'

else:

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

b[i][j] = 'left'

由演算法lcslength計算得到的陣列b可用於快速構造序列x=和y=的最長公共子串行。首先從b[m][n]開始,根據b[i][j]值所指向的方向進行搜尋。equals表示等於,即x和y的最長公共子串行為xi-1和yj-1的最長公共子串行加上xi所得的最長公共子串行,left為向左,即xi和yj的最長公共子串行與xi和yj的最長公共子串行相同,up表示向上,即xi和yj的最長公共子串行與xi-1和yj的最長公共子串行相同。下面lcs演算法為具體的求解過程。

def getlcs(i, j, x=none, b=none):

if i == 0 and j == 0:

return

if b[i][j] == 'equals':

getlcs(i-1,j-1, x, b)

print x[i-1], ' '

elif b[i][j] == 'left':

getlcs(i, j-1, x, b)

else:

getlcs(i-1, j, x, b)

現有兩個序列x=和y=,由演算法lcslength和lcs計算出的結果如圖所示:

#-*-coding:utf8-*-

"""author : xianghonglee

email : [email protected]

created on '14-5-26'

"""def lcslength(m, n, x=none, y=none,c=none, b=none):

for i in range(1, m):

for j in range(1, n):

if x[i-1] == y[j-1]:

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

b[i][j] = 'equals'

elif c[i-1][j] >= c[i][j-1]:

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

b[i][j] = 'up'

else:

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

b[i][j] = 'left'

def getlcs(i, j, x=none, b=none):

if i == 0 and j == 0:

return

if b[i][j] == 'equals':

getlcs(i-1,j-1, x, b)

print x[i-1], ' '

elif b[i][j] == 'left':

getlcs(i, j-1, x, b)

else:

getlcs(i-1, j, x, b)

if __name__ == '__main__':

x ="abcbdab"

y = "bdcaba"

m = len(x)+1

n = len(y)+1

b = [[0 for i in range(n)] for j in range(m)]

c = [[0 for i in range(n)] for j in range(m)]

lcslength(m,n,x,y,c,b)

for i in c:

print i

for j in b:

print j

getlcs(m-1,n-1,x,b)

列印結果為:

python 最長公共子串行

usr bin env python3 coding utf 8 最長公共子串行 fish fosh fsh def findlongestsubstring source,dest 輸入值,要比較的值 inlen len source outlen len dest target cell 0 f...

最長公共子串行 最長公共子串

1 最長公共子串行 採用動態規劃的思想,用乙個陣列dp i j 記錄a字串中i 1位置到b字串中j 1位置的最長公共子串行,若a i 1 b j 1 那麼dp i j dp i 1 j 1 1,若不相同,那麼dp i j 就是dp i 1 j 和dp i j 1 中的較大者。class lcs el...

最長公共子串行 最長公共子串

1.區別 找兩個字串的最長公共子串,這個子串要求在原字串中是連續的。而最長公共子串行則並不要求連續。2 最長公共子串 其實這是乙個序貫決策問題,可以用動態規劃來求解。我們採用乙個二維矩陣來記錄中間的結果。這個二維矩陣怎麼構造呢?直接舉個例子吧 bab 和 caba 當然我們現在一眼就可以看出來最長公...