最長子序列LCS實現

問題描述

已知兩個固定字母序列,求解兩者最長(非連續)子序列長度

實現思路

使用動態規劃思想,將a序列的i長度子序列與b序列的j長度子序列的最長公共子序列看作子問題 s[i,j]
則s[i,j]滿足如下公式
在這裏插入圖片描述

代碼實現

子序列矩陣

import numpy as np

def dplcs(str1, str2):
   s = np.zeros((len(str1) + 1, len(str2) + 1), dtype = np.uint8)
   s[:, 0] = 0
   s[0, :] = 0
   for i in range(len(str1)):
       for j in range(len(str2)):
           if str1[i] == str2[j]:
               s[i + 1, j + 1] = s[i, j] + 1
           else:
               s[i + 1, j + 1] = max(s[i, j + 1], s[i + 1, j])
   return s

a = 'fdjkaspewfnklvd;f'
b = 'fdasjnfxc.vpowewf['
rect = dplcs(a, b)

輸出如下,則最長子序列長度爲右下角值8

[[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
 [0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1]
 [0 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2]
 [0 1 2 2 2 3 3 3 3 3 3 3 3 3 3 3 3 3 3]
 [0 1 2 2 2 3 3 3 3 3 3 3 3 3 3 3 3 3 3]
 [0 1 2 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3]
 [0 1 2 3 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4]
 [0 1 2 3 4 4 4 4 4 4 4 4 5 5 5 5 5 5 5]
 [0 1 2 3 4 4 4 4 4 4 4 4 5 5 5 6 6 6 6]
 [0 1 2 3 4 4 4 4 4 4 4 4 5 5 6 6 7 7 7]
 [0 1 2 3 4 4 4 5 5 5 5 5 5 5 6 6 7 8 8]
 [0 1 2 3 4 4 5 5 5 5 5 5 5 5 6 6 7 8 8]
 [0 1 2 3 4 4 5 5 5 5 5 5 5 5 6 6 7 8 8]
 [0 1 2 3 4 4 5 5 5 5 5 5 5 5 6 6 7 8 8]
 [0 1 2 3 4 4 5 5 5 5 5 6 6 6 6 6 7 8 8]
 [0 1 2 3 4 4 5 5 5 5 5 6 6 6 6 6 7 8 8]
 [0 1 2 3 4 4 5 5 5 5 5 6 6 6 6 6 7 8 8]
 [0 1 2 3 4 4 5 6 6 6 6 6 6 6 6 6 7 8 8]]

最長子序列獲取

最長子序列一般都有多種可能,這裏給出其中一種的獲取代碼

def rdlcs(str1, str2, rect):
    i = len(str1)
    j = len(str2)
    idx_arr = []
    while (rect[i, j] > 0):
        if rect[i, j] == rect[i - 1, j]:
            i -= 1
            continue
        if rect[i, j] == rect[i, j - 1]:
            j -= 1
        else:
            i -= 1
            j -= 1
            idx_arr.append((i, j))
    idx_arr.reverse()
    print(idx_arr)
    print(np.array([s for s in str1])[[x[0] for x in idx_arr]])

rdlcs(a, b, rect.astype(np.uint8))

輸出如下:

[(0, 0), (1, 1), (4, 2), (5, 3), (6, 11), (7, 14), (8, 15), (9, 16)]
['f' 'd' 'a' 's' 'p' 'e' 'w' 'f']
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章