動態規劃演算法之公共子串行

2021-09-07 04:22:32 字數 2952 閱讀 6797

'''description: 1808_公共子串行

檢視 提交 統計 提問

總時間限制: 1000ms 記憶體限制: 65536kb

描述我們稱序列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的最大公共子串行,也就是說要找到乙個最長的序列z,使得z既是x的子串行也是y的子串行。

輸入輸入包括多組測試資料。每組資料報括一行,給出兩個長度不超過200的字串,表示兩個序列。兩個字串之間由若干個空格隔開。

輸出對每組輸入資料,輸出一行,給出兩個序列的最大公共子串行的長度。

樣例輸入

abcfbc         abfcab

programming    contest 

abcd           mnp

樣例輸出42

0'''

from queue import lifoqueue

def lcs_length_1(i, j):

global b

#print(b, x, y)

if b[i][j] != 0:

return b[i][j]

if i == 0 or j == 0:

b[i][j] = 0

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

b[i][j] = lcs_length_1(i-1, j-1) + 1

else:

b[i][j] = max(lcs_length_1(i-1, j), lcs_length_1(i, j-1))

return b[i][j]

def lcs_length_2(n, m):

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

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

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

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

else:

b[i][j] = max(b[i-1][j], b[i][j-1])

return b[n][m]

def lcs_length_3(n, m):

pre = [0] * (m + 1) #pre[j]相當於b[i-1][j]  

cur = [0] * (m + 1) #cur[j]相當於b[i][j] 

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

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

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

cur[j] = pre[j-1] + 1

else:

cur[j] = max(pre[j], cur[j-1])

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

pre[j] = cur[j]

return cur[j]

def print_lcs_1(i, j):

if i == 0 or j == 0:

return

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

print_lcs_1(i-1, j-1)

print("x[{}]={} : y[{}]={}".format(i-1,x[i-1],j-1,y[j-1]))

elif b[i-1][j] > b[i][j-1]:

print_lcs_1(i-1, j)

else:

print_lcs_1(i, j-1)

def print_lcs_2(n, m):

s = lifoqueue()

i, j = n, m

while i > 0 and j > 0:

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

t = "x[{}]={} : y[{}]={}".format(i-1,x[i-1],j-1,y[j-1])

s.put(t)

i, j = i - 1, j - 1

elif b[i-1][j] > b[i][j-1]:

i -= 1

else:

j -= 1

while not s.empty():

print(s.get())

def main():

with open('ggzxl.txt', 'r') as fin:

for line in fin.readlines():   #依次讀取每行  

line = line.strip()      #去掉每行頭尾空白

global b

global x

global y

x, y = tuple(line.split())

b = [[0 for i in range(len(y)+1)] for j in range(len(x)+1)]

l1 = lcs_length_1(len(x), len(y))

print(l1)

print(x, y)

#print(b)

print_lcs_1(len(x), len(y))

b = [[0 for i in range(len(y)+1)] for j in range(len(x)+1)]

l2 = lcs_length_2(len(x), len(y))

print(l2)

print(x, y)

#print(b)

print_lcs_2(len(x), len(y))

l3 = lcs_length_3(len(x), len(y))

print(l3)

x = ""

y = ""

b =

main()

最長公共子串行問題(動態規劃演算法)

問題 給出兩個字串a a1 a2a3 an和b b1 b2b3 bm,求a和b的最長公共子串行的長度。例如 a xyxxzxyzxy,b zxzyyzxxyxxz,則它們的最長公共子串行為xy z,長度為6。注意 最長公共子串行不一定要求連續的字串,只講究先後順序一致。約定 l i,j 表示這樣兩個...

動態規劃演算法之最長公共子串行問題

問題描述 給定兩個字串,尋找這兩個字串之間的最長公共子串行。輸入格式 輸入兩行,分別包含乙個字串,僅含有小寫字母。輸出格式 最長公共子串行的長度。樣例輸入 abcdgh aedfhb 樣例輸出 3樣例說明 最長公共子串行為a,d,h。資料規模和約定 字串長度1 1000。分析 求最長公共子串行,用動...

動態規劃演算法

一 動態規劃演算法原理 將待求解的問題分解成若干個相互聯絡的子問題,先求解子問題,然後從這些子問題的解得到原問題的解 對於重複出現的子問題,只在第一次遇到的時候對它進行求解,並把答案儲存起來。了不去求解相同的子問題,引入乙個陣列,把所有子問題的解存於該陣列中,這就是動態規劃所採用的基本方法。動態規劃...