python3 lcs 最大公共子序列


拋出問題:

  假定字符串 s1 = 'BDCABA', s2 = 'ABCBDAB',求s1和s2的最大公共子序列。

問題分析:

  我們想要求出s1和s2的最大公共子序列,我們可以用c(i,j)表示s1(i)和s2(j)最大公共子序列的長度,

   假定c(i,j) = m,

     如果:s1[ i ]s2[ j ]相等,那么推出c(i,j) = c(i-1,j-1)  + 1,

  如果:s1[ i ] 和 s2[ j ]不相等,那么得到c(i,j) = max(c(i,j-1),c(i-1,j))

  總結為公式就是:

畫成表格更清楚,也就是如下圖,表格的數即為當前的最大公共子序列的值,箭頭即為該結果是怎么得來的

例如第5行,第5列,因為第5列的c和第5行c相等,所以就等於,第4行,第4列的值+1等到2

  得到了這個值列表,就可以通過回溯的方法,從最后一個值,倒着按照箭頭的方向,依次記錄每個相等的值(也就是方向是左上的值),得到的結果就是我們要求的最終結果

代碼實現:

# -*- coding:utf-8  -*-
# 日期:2018/6/9 15:44
# Author:小鼠標
# 求最長公共子序列
from numpy import *
s1 = 'BDCABA'
s2 = 'ABCBDAB'

def val_list(s1,s2):
    # 兩個字符串的長度
    len_s1 = len(s1) + 1
    len_s2 = len(s2) + 1
    # 方向列表
    direction_list = []
    # 生成len_s2+1行len_s1+1列的全0列表
    res = zeros((len_s2,len_s1))
    direction = zeros((len_s2,len_s1))
    # print(res_list)
    for i in range(0, len_s2-1):
        for j in range(0, len_s1-1):
            #判斷是否相等
            if s1[j] == s2[i]:
                res[i + 1, j + 1] = res[i, j] + 1
                # 1左上 2 上 3左
                direction[i + 1, j + 1] = 1
            else:
                if res[i + 1, j] > res[i, j + 1]:
                    res[i + 1, j + 1] = res[i + 1, j]
                    direction[i + 1, j + 1] = 3
                else:
                    res[i + 1, j + 1] = res[i, j + 1]
                    direction[i + 1, j + 1] = 2
    return res,direction
res ,direction= val_list(s1,s2)
#方向列表 1左上 2 上 3左
# [[0. 0. 0. 0. 0. 0. 0.]
#  [0. 2. 2. 2. 1. 3. 1.]
#  [0. 1. 3. 3. 2. 1. 3.]
#  [0. 2. 2. 1. 3. 2. 2.]
#  [0. 1. 2. 2. 2. 1. 3.]
#  [0. 2. 1. 2. 2. 2. 2.]
#  [0. 2. 2. 2. 1. 2. 1.]
#  [0. 1. 2. 2. 2. 1. 2.]]



#最大子序列的值列表
# [[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.]]

#回溯 遞歸求出結果
global s_res
s_res = ''
def Lcs_fun(s,res_list,i,j):
    if res_list[i,j] == 3:
        Lcs_fun(s,res_list,i,j-1)

    elif res_list[i,j] == 2:
        Lcs_fun(s,res_list,i-1,j)

    elif res_list[i,j] == 1:
        Lcs_fun(s,res_list,i-1,j-1)
        global s_res
        s_res += s[i-1]
    else:
        return
Lcs_fun(s2,direction,len(s2),len(s1))
print(s_res)

這塊很容易就看暈了,仔細看,應該能看懂

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM