zoukankan      html  css  js  c++  java
  • [python] 获得所有的最长公共子序列

    两句闲话

      得到两个序列的最长公共子序列(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
    

      

  • 相关阅读:
    Java 对象初始化
    Java 栈和堆
    值得细品
    磁盘的分区、格式化与挂载
    VirtualBox预存空间不足
    做个备忘
    SQL查数据库有哪些触发器,存储过程...
    SQL 中 CASE
    FMX的Style中的Effects的注意问题
    Python图像处理库(2)
  • 原文地址:https://www.cnblogs.com/super-zhang-828/p/6486452.html
Copyright © 2011-2022 走看看