1. 程式人生 > >python實現最長公共子序列的求解

python實現最長公共子序列的求解

(待完善...)

最長公共子序列是動態規劃基本題目,下面按照動態規劃基本步驟解出來。

1.找出最優解的性質,並刻劃其結構特徵

序列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]的最長公共子序列長度就是MAX(a[:m-1]和b[:n]的最長公共子序列長度,a[:m]和b[:n-1]的最長公共子序列長度)。

2.遞迴定義最優值

c[i,j] = \left\{\begin{matrix} 0 & i=0 \, \, or\, \, j =0\\ c[i-1, j-1]+1& i,j>0\! \; \; and\, \: x_{i} = y_{j}\\ max(c[i,j-1],c[i-1,j])&i,j>0\, \: \: and\: \: x_{i} \neq y_{j} \end{matrix}\right.

3.自底向上根據最優值的資訊來構造最優解

def lcs(a, b):
    lena = len(a)
    lenb = len(b)
    c = [[0 for i in range(lenb + 1)] for j in range(lena + 1)]
    flag = [[0 for i in range(lenb + 1)] for j in range(lena + 1)]
    for i in range(lena):
        for j in range(lenb):
            if a[i] == b[j]:
                c[i + 1][j + 1] = c[i][j] + 1
                flag[i + 1][j + 1] = 'ok'
            elif c[i + 1][j] > c[i][j + 1]:
                c[i + 1][j + 1] = c[i + 1][j]
                flag[i + 1][j + 1] = 'left'
            else:
                c[i + 1][j + 1] = c[i][j + 1]
                flag[i + 1][j + 1] = 'up'
    return flag

def printLcs(flag, a, i, j):
    if i == 0 or j == 0:
        return
    if flag[i][j] == 'ok':
        printLcs(flag, a, i - 1, j - 1)
        print(a[i - 1], end='')
    elif flag[i][j] == 'left':
        printLcs(flag, a, i, j - 1)
    else:
        printLcs(flag, a, i - 1, j)

a = 'ABCBDAB'
b = 'BDCABA'
flag = lcs(a, b)
printLcs(flag, a, len(a), len(b))