Python實現最長公共子串行(查重基礎演算法)

2021-09-02 08:09:42 字數 3116 閱讀 7402

一、問題描述

給定乙個序列x = ,另乙個序列z = 是x的子串行,如果存在乙個嚴格遞增的x中元素下標的序列,使得xij = zj (1<=j<=k)。

給定兩個序列x和y,當另一串行z既是x的子串行又是y的子串行時,稱z是序列x和y的公共子串行。最長公共子串行就是公共子串行中長度最長的子串行。

接下來簡單明瞭地舉例。x = ,x的子串行就是x序列元素按順序組成的乙個子集,比如 ,等。給定另乙個序列y = ,則就是x、y的乙個子串行,而、則是x、y的最長公共子串行。

二、最優子結構證明

假設序列x = ,序列y = ,序列z = 為序列x和y的某個最長公共子串行。那麼:

①若xm = yn,那麼zk=xm=yn,且zk-1就是xm-1和yn-1的乙個最長公共子串行。

②若xm ≠ yn,且zk ≠ xm,那麼zk就是xm-1和yn的乙個最長公共子串行。

③若xm ≠ yn,且zk ≠ yn,那麼zk就是xm和yn-1的乙個最長公共子串行。

證明:①由已知,假設zk ≠ xm,那麼則可以把xm(yn)放在公共子串行zk的末尾,這樣就形成了乙個新的公共子串行,且這個公共子串行的長度 = 原來的序列z長度 + 1,與假設矛盾,所以  zk=xm=yn。再假設zk-1不是xm-1和yn-1的最長公共子串行,說明存在乙個更長的子串行,這時再把xm(yn)附在這個更長子序列的後面,則得到乙個x和y的更長的公共子串行,它的長度 > 原來的z序列長度,與z是x和y的最長公共子串行矛盾,所以①成立。

②由已知,假設zk不是xm-1和yn的最長公共子串行,那麼存在乙個比zk更長的序列是xm-1和yn的公共子串行,而這個更長的序列肯定也是xm和yn的公共子串行,這個序列長度 > 原來z序列,與z是x和y的最長公共子串行矛盾,所以②成立。

③ 同②。    

三、遞迴方程

用c[i][j]表示xi和yj的最長公共子串行的長度。

0                             if i = 0 or j = 0

c[i][j] = c[i-1][j-1] + 1              if i,j>0 and xi= yj

max   if i,j>0 and xi ≠ yj

四、  python**實現(包括輸出最長公共子串行)

import copy

def dplength(x, y, c, b):

for i in range(1, m+1):

for j in range(1, n+1):

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

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

b[i][j] = 1 # 1表示該字元是在公共子串行當中的

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

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

b[i][j] = 0 # 0表示不在公共子串行中

else:

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

b[i][j] = 2 # 2表示不在公共子串行但與0不同

return b and c

def printlcs(b, x, i, j): #列印重複部分

if i == 0 or j == 0:

return 0

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

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

print(x[i-1])  #注意二維列表中的i、j與x、y序列(列表)差1

elif b[i][j] == 0:

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

else:

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

if __name__ == '__main__':

x = list(input())

y = list(input())

print(x)

print(y)

m = len(x)

n = len(y)

c = [ for i in range(m+1)]

for i in range(m+1):

for j in range(n+1):

b = copy.deepcopy(c)

dplength(x, y, c, b)

printlcs(b, x, m, n)

print(c)

print("x在y中的重複率達到:", c[m][n]/n*100, "%")

print("y在x中的重複率達到:", c[m][n]/m*100, "%")

五、實驗結果

輸入:x:abcbdab

y:  bdcaba

輸出:abcbdab

bdcaba

['a', 'b', 'c', 'b', 'd', 'a', 'b']

['b', 'd', 'c', 'a', 'b', 'a']

[[0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0]]bc

ba[[0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 1, 1, 1], [0, 1, 1, 1, 1, 2, 2], [0, 1, 1, 2, 2, 2, 2], [0, 1, 1, 2, 2, 3, 3], [0, 1, 2, 2, 2, 3, 3], [0, 1, 2, 2, 3, 3, 4], [0, 1, 2, 2, 3, 4, 4]]

[[0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 1, 2, 1], [0, 1, 2, 2, 0, 1, 2], [0, 0, 0, 1, 2, 0, 0], [0, 1, 0, 0, 0, 1, 2], [0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 1], [0, 1, 0, 0, 0, 1, 0]]

x在y中的重複率達到: 66.66666666666666 %

y在x中的重複率達到: 57.14285714285714 %

process finished with exit code 0

最長公共子串行python實現

最長公共子串行是動態規劃基本題目,下面按照動態規劃基本步驟解出來。序列a共有m個元素,序列b共有n個元素,如果a m 1 b n 1 那麼a m 和b n 的最長公共子串行長度就是a m 1 和b n 1 的最長公共子串行長度 1 如果a m 1 b n 1 那麼a m 和b n 的最長公共子串行長...

最長公共子串行python實現

1 dp基本思路 公共子串行最優子結構 將問題分解表成更簡單的子問題,這個子問題可以分解成更多的子問題使用動態規劃演算法求解,這個過程需要在乙個表中儲存同一級別的子問題的解,因此這個解可以被更高階的子問題使用。2 問題的解 定義兩個序列x y,二維陣列f i j 表示x的i位和y的j位之前的最長公共...

python實現最長公共子串行

最長公共子串行python實現,最長公共子串行是動態規劃基本題目,下面按照動態規劃基本步驟解出來。1.找出最優解的性質,並刻劃其結構特徵 序列a共有m個元素,序列b共有n個元素,如果a m 1 b n 1 那麼a m 和b n 的最長公共子串行長度就是a m 1 和b n 1 的最長公共子串行長度 ...