两句闲话

  得到两个序列的最长公共子序列(LCS)是个经典问题,使用动态规划,实现起来并不难。

  一般来说,我们只是输出一个LCS。但是,老师布置的作业是输出所有的LCS。

解法

  按照一般的方法,我们首先得到一个矩阵,然后从矩阵的右下角开始回溯。回溯时,我们选择较大的数字,以向左,或向上,或向左上。但当数字相等时,我们往往会随便向某一个方向回溯,这样的话,我们就只会得到一个LCS。因此,很容易想到,所有的LCS会构成一棵树,我们只需要对这棵树进行先序遍历,就可得到所有的LCS。

  

  代码如下

#python 3.5

class LCS_naive:
"""
最长公共子序列:
通过动态规划,得到矩阵D,
并从矩阵D中读出一个最长公共子序列
不支持读出所有的LCS
"""
def __init__(self):
self.matrix=[[]] def init(self,str1,str2):
self.str1=str1
self.str2=str2
self.len1=len(str1)
self.len2=len(str2)
self.matrix=[[0 for i in range(self.len2+1)]for j in range(self.len1+1)] def _get_matrix(self):
"""通过动态规划,构建矩阵"""
for i in range(self.len1):
for j in range(self.len2):
if self.str1[i]==self.str2[j]:
self.matrix[i+1][j+1]=self.matrix[i][j]+1
else:
self.matrix[i+1][j+1]=max(self.matrix[i][j+1],self.matrix[i+1][j]) def _matrix_show(self,matrix):
"""展示通过动态规划所构建的矩阵"""
print ("----matrix-----")
print (" "," ",end=" ")
for ch in self.str2:
print (ch,end=" ")
print ()
for i in range(len(matrix)):
if i>0: print (self.str1[i-1],end=" ")
else: print (" ",end=" ")
for j in range(len(matrix[i])):
print (matrix[i][j],end=" ")
print ()
print ("---------------") def _get_one_lcs_from_matrix(self):
i=len(self.matrix)-1
if i==0:
print ("matrix is too small")
return
j=len(self.matrix[0])-1
res=[]
while not (i==0 or j==0):
if self.str1[i-1]==self.str2[j-1]:
res.append(self.str1[i-1])
i-=1
j-=1
else:
if self.matrix[i-1][j]>self.matrix[i][j-1]:
i=i-1
else:
j=j-1
return "".join(res[::-1]) def get_lcs(self):
self._get_matrix()
self._matrix_show(self.matrix)
lcs=self._get_one_lcs_from_matrix()
print (lcs) class LCS(LCS_naive):
"""
继承自LCS_naive
增加获取所有LCS的支持
"""
def __init__(self):
LCS_naive.__init__(self) def _get_all_lcs_from_matrix(self):
self._pre_travesal(self.len1,self.len2,[]) def _pre_travesal(self,i,j,lcs_ted):
if i==0 or j==0:
print ("".join(lcs_ted[::-1]))
return
if self.str1[i-1]==self.str2[j-1]:
lcs_ted.append(self.str1[i-1])
self._pre_travesal(i-1,j-1,lcs_ted)
else:
if self.matrix[i-1][j]>self.matrix[i][j-1]:
self._pre_travesal(i-1,j,lcs_ted)
elif self.matrix[i-1][j]<self.matrix[i][j-1]:
self._pre_travesal(i,j-1,lcs_ted)
else:
###### 分支
self._pre_travesal(i-1,j,lcs_ted[:])
self._pre_travesal(i,j-1,lcs_ted) def get_lcs(self):
self._get_matrix()
self._matrix_show(self.matrix)
self._get_all_lcs_from_matrix() l=LCS()
l.init("ABCBDAB","BDCABA")
l.get_lcs()

输出结果

----matrix-----
B D C A B A
0 0 0 0 0 0 0
A 0 0 0 0 1 1 1
B 0 1 1 1 1 2 2
C 0 1 1 2 2 2 2
B 0 1 1 2 2 3 3
D 0 1 2 2 2 3 3
A 0 1 2 2 3 3 4
B 0 1 2 2 3 4 4
---------------
BCBA
BCAB
BDAB

  

[python] 获得所有的最长公共子序列的更多相关文章

  1. 最长公共子序列python实现

    最长公共子序列是动态规划基本题目,以下依照动态规划基本步骤解出来. 1.找出最优解的性质,并刻划其结构特征 序列a共同拥有m个元素,序列b共同拥有n个元素,假设a[m-1]==b[n-1],那么a[: ...

  2. 用Python计算最长公共子序列和最长公共子串

    如何用Python计算最长公共子序列和最长公共子串 1. 什么是最长公共子序列?什么是最长公共子串? 1.1. 最长公共子序列(Longest-Common-Subsequences,LCS) 最长公 ...

  3. python实现查找最长公共子序列

    #!/usr/bin/python # -*- coding: UTF-8 -*- worlds = ['fosh','fort','vista','fish','hish','hello','ohd ...

  4. 【python】Leetcode每日一题-最长公共子序列

    [python]Leetcode每日一题-最长公共子序列 [题目描述] 给定两个字符串 text1 和 text2,返回这两个字符串的最长 公共子序列 的长度.如果不存在 公共子序列 ,返回 0 . ...

  5. 用python实现最长公共子序列算法(找到所有最长公共子串)

    软件安全的一个小实验,正好复习一下LCS的写法. 实现LCS的算法和算法导论上的方式基本一致,都是先建好两个表,一个存储在(i,j)处当前最长公共子序列长度,另一个存储在(i,j)处的回溯方向. 相对 ...

  6. 【ZH奶酪】如何用Python计算最长公共子序列和最长公共子串

    1. 什么是最长公共子序列?什么是最长公共子串? 1.1. 最长公共子序列(Longest-Common-Subsequences,LCS) 最长公共子序列(Longest-Common-Subseq ...

  7. python 回溯法 子集树模板 系列 —— 14、最长公共子序列(LCS)

    问题 输入 第1行:字符串A 第2行:字符串B (A,B的长度 <= 1000) 输出 输出最长的子序列,如果有多个,随意输出1个. 输入示例 belong cnblogs 输出示例 blog ...

  8. 动态规划1——最长递增子序列、最长公共子序列、最长公共子串(python实现)

    目录 1. 最长递增序列 2. 最长公共子序列 3. 最长公共子串 1. 最长递增序列 给定一个序列,找出其中最长的,严格递增的子序列的长度(不要求连续). 解法一:动态规划 通过一个辅助数组记录每一 ...

  9. [Python]最长公共子序列 VS 最长公共子串[动态规划]

    前言 由于原微软开源的基于古老的perl语言的Rouge依赖环境实在难以搭建,遂跟着Rouge论文的描述自行实现. Rouge存在N.L.S.W.SU等几大子评估指标.在复现Rouge-L的函数时,便 ...

随机推荐

  1. Java8中时间日期库的20个常用使用示例

    除了lambda表达式,stream以及几个小的改进之外,Java 8还引入了一套全新的时间日期API,在本篇教程中我们将通过几个简单的任务示例来学习如何使用Java 8的这套API.Java对日期, ...

  2. Python单元测试框架——unittest

    测试的常用规则 一个测试单元必须关注一个很小的功能函数,证明它是正确的: 每个测试单元必须是完全独立的,必须能单独运行.这样意味着每一个测试方法必须重新加载数据,执行完毕后做一些清理工作.通常通过se ...

  3. shell中的调试与计算

    shell 计算  2.正确方法   1)使用let   var=1   let "var+=1"   echo $var   输出结果为2,这次没有悲剧   注意:   a)经我 ...

  4. 【JavaScript】用JS绘制一个球

    参考: 1.http://www.w3school.com.cn/html5/html_5_canvas.asp 2.http://blog.csdn.net/qq_27626333/article/ ...

  5. 【笔记】Maven使用入门

    参考<maven实战> 1.编写POM 2.编写主代码 3.编写测试代码 4.打包和运行 具体如下: 1.编写POM. <!-- XML头,指定了该xml文档的版本和编辑方式 --& ...

  6. JMeter接口测试和压力测试

    JMeter接口测试和压力测试 JMeter可以做接口测试和压力测试.其中接口测试的简单操作包括做http脚本(发get/post请求.加cookie.加header.加权限认证.上传文件).做web ...

  7. spring security采用基于简单加密 token 的方法实现的remember me功能

    记住我功能,相信大家在一些网站已经用过,一些安全要求不高的都可以使用这个功能,方便快捷. spring security针对该功能有两种实现方式,一种是简单的使用加密来保证基于 cookie 的 to ...

  8. 【bzoj5427】最长上升子序列(贪心+LIS)

    题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=5427 因为noip,博客咕了好久,这几天集中填一下坑. 这题我们可以假设往不确定的空位 ...

  9. hibernate的一对多配置

    首先是“一”的 Customer.java package com.xiaostudy.domain; import java.util.HashSet; import java.util.Set; ...

  10. Mongodb笔记(三)user && aggregate && mapReduce

    版本:mongodb3.4. User: mongodb使用验证登录:默认不开启,mongod中使用--auth开启:  mongod -port=3000 --auth  : 基本方法: db.cr ...