最长子序列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']
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章