我是靠谱客的博主 帅气火车,最近开发中收集的这篇文章主要介绍四、Dynamic-programming algorithm Dynamic--LCS1 问题2 算法3 代码实现,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

(学习笔记,无什参考价值!)

1 问题

在这里插入图片描述

2 算法

2.1 Brute-force LCS algorithm

在这里插入图片描述

  • 检查每一个subsequence是否是 y y y的子列时,遍历 y y y的每一个元素,看是否依次可以全部覆盖subsequence所有元素,所以其复杂度为 O ( n ) O(n) O(n);

2.2 Dynamic-programming hallmark #1

  • 动态规划的第一特征–最优子结构,下面用定理的方式证明这种特征;
    在这里插入图片描述

  • 这个性质是说,一个规模稍大的最优解问题建立在一些规模较小的最优解问题基础之上,由此解决问题的思路就有两个方向:自顶向下的递归方式、自底向上的方式。
    在这里插入图片描述

  • 很容易可以推出下面的(数量上的)性质:
    在这里插入图片描述

  • 由上面的递归公式,首先想到的是使用递归实现:
    在这里插入图片描述

  • 下面用递归树分析递归实现的时间复杂度:
    在这里插入图片描述

  • 递归树的高度就是指数,所以时间复杂度是指数级别,和暴力解法没有什么大提高!

  • 从上面递归树图中观察到一个现象:递归树中存在大量重复的子问题,这些是导致递归算法龟速的原因,也是动态规划诞生的另外一个必要条件。

2.3 Dynamic-programming hallmark #2

  • 动态规划的第二特征–大量重复子问题
    在这里插入图片描述

  • 有了这个特征,此时有两条改进思路,一是在递归过程中,存储算过的每一个子问题。算法描述如下:

在这里插入图片描述

  • 另外一个改进思路是自底向上算法:
    在这里插入图片描述
  • 在上面自底向上的计算过程中,同时做了最优数值记录和最优路径记录这两件事,路径本质是:记录每一步由哪一个子问题得到父问题的解,路径的起点是(1,1),终点是(m,n),从终点到起点依照“来的时候做的箭头标记”,可以完整的回到起点,其中路径中标记’↘’路标的坐标点是最优解中的点。
  • 手工演示如下:
    在这里插入图片描述

2.4 打印最优解

  • 依照上面的分析可以很容易找到一个倒序的LCS,结合递归实现原理,正好可以正序打印出LCS,算法如下:
    在这里插入图片描述
  • 看这段代码,直觉上感觉还是倒序输出LCS,但是仔细考虑一下递归底层的运行过程,递归中的“递”就是入栈,递进;“归”就是出栈,回归,以倒序压入到栈中,以正序出栈;

3 代码实现

# -*- coding: utf-8 -*-
import numpy as np


def LCS_LENGTH(X, Y):
    m = len(X)
    n = len(Y)
    b = np.array([0] * (m * n)).reshape((m, n))
    c = np.array([0] * (m * n)).reshape((m, n))
    for i in range(1, m):
        c[i][0] = 0
    for j in range(0, n):
        c[0][j] = 0
    for i in range(1, m):
        for j in range(1, n):
            if X[i] == Y[j]:
                c[i][j] = c[i - 1][j - 1] + 1
                b[i][j] = 0
            elif c[i - 1][j] >= c[i][j - 1]:
                c[i][j] = c[i - 1][j]
                b[i][j] = '1'
            else:
                c[i][j] = c[i][j - 1]
                b[i][j] = '-1'
    return c, b


def PRINT_LCS(b, X, i, j):
    if i == 0 or j == 0:
        return
    if b[i][j] == 0:
        PRINT_LCS(b, X, i - 1, j - 1)
        print(X[i])
    elif b[i][j] == 1:
        PRINT_LCS(b, X, i - 1, j)
    else:
        PRINT_LCS(b, X, i, j - 1)


if __name__ == '__main__':
    X = ['x', 'A', 'B', 'C', 'B', 'D', 'A', 'B']
    Y = ['x', 'B', 'D', 'C', 'A', 'B', 'A']
    c, b = LCS_LENGTH(X, Y)
    PRINT_LCS(b, X, len(X) - 1, len(Y) - 1)

运行结果:

B
C
B
A

最后

以上就是帅气火车为你收集整理的四、Dynamic-programming algorithm Dynamic--LCS1 问题2 算法3 代码实现的全部内容,希望文章能够帮你解决四、Dynamic-programming algorithm Dynamic--LCS1 问题2 算法3 代码实现所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(53)

评论列表共有 0 条评论

立即
投稿
返回
顶部