栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

算法:最长公共子序列(输出所有最长公共子序列/Python实现)

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

算法:最长公共子序列(输出所有最长公共子序列/Python实现)

前言:

如何求最长公共子序列的长度相信大家都很熟悉,但是如何求出最长公共子序列的所有可能结果呢?接下来,就让小编带大家了解一下小编使用的方法吧。

问题描述:

我们先给定两个序列,以这个为例,求出它们最长公共子序列的所有可能,并储存入列表后输出。

s1 = '357486782'

s2 = '13456778'

基本流程:

阶段一:找出最长公共子序列长度。

现在我们先研究如何找出最长公共子序列长度的问题,我们先把s1和s2的内容排成一行和一列,组成个图表,并在第一个留空,然后将留空的行列全部填上0。

方法出自动态规划 最长公共子序列 过程图解_hrn1216的博客-CSDN博客_最长公共子序列

思路一:

1.分别以s1和s2的序列做横纵坐标,在第一行第一列填满0,如图所示。

2.遍历s2的所有元素,每个元素都匹配一遍s1的所有元素。

        2.1两者不同则取左边第一个数和上面第一个数中最大的一个填入。

        2.2 两者相同则在左上角数的基础上加1

 

        2.3 以此方式填满列表,并把以2.2方法得到的数打上黄色标记。

代码初步实现:

为了方便索引,我们先设置四个变量名用以储存,其所代表的内容如图所示。

lx,ly,ix,iy四个变量名

现在我们整理一下上述的方法,并将其对应的代码实现写出来,如图所示。

 

代码完整实现: 

阶段二:找出所有的最长公共子序列。

思路二:

1.在思路一中打上黄色标记的数,以(目前最长公共子序列长度,iy,ix)的方式建立对应的辅助坐标。

辅助坐标的意义:

判断两个数能不能出现在同一个最长公共子序列里,在此我们基于一个假设:

若有两个结果数,A-(a1,iy1,ix1),B-(a2,iy2,ix2)

当iy2>iy1, ix2>ix1且a2 = a1+1时,可有“AB“序列

(这个假设我自己想的,可能不对,如有问题还请大家指出)

 

 代码实现:

2.将辅助坐标排序,这里使用了快速排序算法。

代码实现:

 

使用算法排序后打印出来的结果:

 

3.处理结果(n_arr):

最长公共子序列长度为5,意味着一个最长公共子序列有五个位置,按照这个位置

将结果数和坐标进行分组,将列表内的结果数和坐标进行分离,分别储存在两个列表里。

 

代码实现: 

 

获得的结果 

 

4.进行三层嵌套的for循环

第一层遍历l_arr,获得元素

第二层遍历l_arr遍历到的的当前元素,

第三次遍历l_arr的当前元素的下个元素。

从五个组中分别给五个位置取数

 5.将坐标转换成字符串,这个代码得出的结果可能会有重复,因此转换成字符串后再用集合去重

完整代码:

s1 = '357486782'
s2 = '13456778'
lx = []
ly = []
for i in range(len(s1)+1):
    lx.append(0)
ly.append(lx)
# 2.进行字符匹配
iy = 0  # 记录横向列表的序数
# 建立两个列表,一放结果数,二放结果数的一维数组
n_arr = []  # 结果数和对应的一维数组-(序数,纵坐标,横坐标)
dic_n_arr = {}  # 以字典的形式存储结果数和对应的一维数组-(序数,纵坐标,横坐标)
for y in range(len(s2)):
    iy += 1
    ix = 0 # 记录横向列表内每个元素的序数
    ly.append([0])
    for x in range(len(s1)):
        ix += 1
        if s2[y] != s1[x]:
            val = max(ly[iy][ix-1], ly[iy-1][ix])
        else:
            val = ly[iy-1][ix-1]+1
            n_arr.append([s2[iy - 1], (val, iy, ix)])
            dic_n_arr[(val, iy, ix)] = s2[iy - 1]
        ly[iy].append(val)
print('数组建立结束')
# 目的:输出所有可能的最长子序列
# 1.建两个列表,一放结果数,二放结果数的一维数组
# 2.排序 --- 用快速排序的算法进行迭代
def quicksort_b(arr): # 列表 l_res 为参
    if len(arr) <= 1:
        return arr
    else:
        prvot = arr[0][1][0]
        # 以目标为要求,从arr里挑出符合要求的数。
        l = [i for i in arr[1:] if i[1][0] <= prvot] # 遍历除第一个以外的数,小的放左边
        r = [i for i in arr[1:] if i[1][0] > prvot]
        l = quicksort_b(l)
        r = quicksort_b(r)
        return l+[arr[0]]+r
print(n_arr)
print('数组排序结束')
n_arr = quicksort_b(n_arr)
print(n_arr)
l_n = [] # 存放结果的列表
l_arr = [] # 存放坐标的列表
for i in range(len(n_arr)):
    if n_arr[i][1][0] > len(l_n):
        l_n.append([])
        l_arr.append([])
    l_n[-1].append(n_arr[i][0])
    l_arr[-1].append(n_arr[i][1])
print(l_n)
print(l_arr)
last_arr = [] # 存放最后结果的列表
for a in range(len(l_arr)):
    if a == 0:
        for b in l_arr[a]: # 遍历las_a里第一个[]的所有元素
            last_arr.append([b])
    else:
        ll = len(last_arr)  # lis是内含一层列表的列表,c即为一个列表,里面储存结果数
        for b in l_arr[a]: # las_a是内含一层的列表,las_a[a]为一个列表,b为一个元素
            #print('b:', b)
            for c in range(ll): # ll是最外列表的索引值,c即为一个列表,里面储存结果数
                c = last_arr[c] # c即为一个列表,里面储存结果数
                #print('c:',c)
                if c[-1][1] < b[1] and c[-1][2] < b[2]:
                    h = c[:]  # 将c里除最后一个元素外,全复制下来
                    h.append(b)
                    last_arr.append(h)
        del last_arr[:ll]
print('数组出结果结束')
# print('n_arr:', n_arr) # 将元素(n)和对应的坐标(arr)合并,方便排序
# print('dic_n_arr:', dic_n_arr) # 将元素(n)和对应的坐标(arr)合并,方便查找
# print('l_n:', l_n)  # 存放结果元素的列表
# print('l_arr:', l_arr)  # 存放结果元素对应的坐标的列表
# print('last_arr:', last_arr) # 存放最后结果的列表,以坐标形式
# 将坐标转换成具体字符
last_n = [] # 存放最后结果的列表,以具体元素形式
for i in last_arr:
    lis = []
    for j in i:
        lis.append(dic_n_arr[j])
    last_n.append(lis)
last_s = [] # 存放最后结果的列表,以字符串形式
for i in last_n:
    newi = ''.join(i)
    last_s.append(newi)
# 删除重复元素
last = set(last_s)
print('所有可能的最长公共子序列:', last)

 

 

 

 

 

 

 

 

 

 

 

 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/304028.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号