zoukankan      html  css  js  c++  java
  • python3 lcs 最大公共子序列

    抛出问题:

      假定字符串 s1 = 'BDCABA', s2 = 'ABCBDAB',求s1和s2的最大公共子序列。

    问题分析:

      我们想要求出s1和s2的最大公共子序列,我们可以用c(i,j)表示s1(i)和s2(j)最大公共子序列的长度,

       假定c(i,j) = m,

         如果:s1[ i ]s2[ j ]相等,那么推出c(i,j) = c(i-1,j-1)  + 1,

      如果:s1[ i ] 和 s2[ j ]不相等,那么得到c(i,j) = max(c(i,j-1),c(i-1,j))

      总结为公式就是:

    画成表格更清楚,也就是如下图,表格的数即为当前的最大公共子序列的值,箭头即为该结果是怎么得来的

    例如第5行,第5列,因为第5列的c和第5行c相等,所以就等于,第4行,第4列的值+1等到2

      得到了这个值列表,就可以通过回溯的方法,从最后一个值,倒着按照箭头的方向,依次记录每个相等的值(也就是方向是左上的值),得到的结果就是我们要求的最终结果

    代码实现:

    # -*- coding:utf-8  -*-
    # 日期:2018/6/9 15:44
    # Author:小鼠标
    # 求最长公共子序列
    from numpy import *
    s1 = 'BDCABA'
    s2 = 'ABCBDAB'
    
    def val_list(s1,s2):
        # 两个字符串的长度
        len_s1 = len(s1) + 1
        len_s2 = len(s2) + 1
        # 方向列表
        direction_list = []
        # 生成len_s2+1行len_s1+1列的全0列表
        res = zeros((len_s2,len_s1))
        direction = zeros((len_s2,len_s1))
        # print(res_list)
        for i in range(0, len_s2-1):
            for j in range(0, len_s1-1):
                #判断是否相等
                if s1[j] == s2[i]:
                    res[i + 1, j + 1] = res[i, j] + 1
                    # 1左上 2 上 3左
                    direction[i + 1, j + 1] = 1
                else:
                    if res[i + 1, j] > res[i, j + 1]:
                        res[i + 1, j + 1] = res[i + 1, j]
                        direction[i + 1, j + 1] = 3
                    else:
                        res[i + 1, j + 1] = res[i, j + 1]
                        direction[i + 1, j + 1] = 2
        return res,direction
    res ,direction= val_list(s1,s2)
    #方向列表 1左上 2 上 3左
    # [[0. 0. 0. 0. 0. 0. 0.]
    #  [0. 2. 2. 2. 1. 3. 1.]
    #  [0. 1. 3. 3. 2. 1. 3.]
    #  [0. 2. 2. 1. 3. 2. 2.]
    #  [0. 1. 2. 2. 2. 1. 3.]
    #  [0. 2. 1. 2. 2. 2. 2.]
    #  [0. 2. 2. 2. 1. 2. 1.]
    #  [0. 1. 2. 2. 2. 1. 2.]]
    
    
    
    #最大子序列的值列表
    # [[0. 0. 0. 0. 0. 0. 0.]
    # [0. 0. 0. 0. 1. 1. 1.]
    # [0. 1. 1. 1. 1. 2. 2.]
    # [0. 1. 1. 2. 2. 2. 2.]
    # [0. 1. 1. 2. 2. 3. 3.]
    # [0. 1. 2. 2. 2. 3. 3.]
    # [0. 1. 2. 2. 3. 3. 4.]
    # [0. 1. 2. 2. 3. 4. 4.]]
    
    #回溯 递归求出结果
    global s_res
    s_res = ''
    def Lcs_fun(s,res_list,i,j):
        if res_list[i,j] == 3:
            Lcs_fun(s,res_list,i,j-1)
    
        elif res_list[i,j] == 2:
            Lcs_fun(s,res_list,i-1,j)
    
        elif res_list[i,j] == 1:
            Lcs_fun(s,res_list,i-1,j-1)
            global s_res
            s_res += s[i-1]
        else:
            return
    Lcs_fun(s2,direction,len(s2),len(s1))
    print(s_res)

    这块很容易就看晕了,仔细看,应该能看懂

  • 相关阅读:
    compose 函数实现
    垂直居中的实现方式
    数组去重方法总结
    前端性能优化
    简简单单的几个正则表达式
    ES6
    Vue不兼容IE8原因以及Object.defineProperty详解
    Vuex(二)——关于store
    Vuex(一)——vuejs的状态管理模式
    关于REST的浅显了解
  • 原文地址:https://www.cnblogs.com/7749ha/p/9160868.html
Copyright © 2011-2022 走看看