算法学习-LCS 最长公共子序列

算法学习-LCS 最长公共子序列

0x01 摘要

LCS
全称Longest Common Subsequence,即最长公共子序列问题。本文实现代码采用Python

0x02 思路

首先我们想到的是用递归的方式,此方法思考起来比较简单,但缺点是会有重复计算,性能较低。

该问题其实就是父问题和子问题的关系,可以考虑采用动态规划算法。

记状态转移二维数组dp[i][j]表示从 字符串a中下标 0到i-1 和 字符串b中0到j-1 的最长公共子序列。

经过推导可以得出状态转移方程如下:

# 当a[i-1] == b[j-1]时
dp[i][j] = dp[i-1][j-1] + a[i-1]

# 当len(dp[i-1][j]) > len(dp[i][j-1])
dp[i][j] = dp[i-1][j]

# 否则
dp[i][j] = dp[i][j-1]

从1到len+1遍历a、b字符串,最终得到的 dp[len_a][len_b]便是最终结果,代表字符串a和字符串b的最长公共子序列。

0x03 动态规划实现代码

python实现代码如下:

# -*- coding:utf-8 -*-

# 动态规划思想求解最长公共子序列
def lcs_dynamic_planning(a, b):
    len_a = len(a)
    len_b = len(b)
    # 创建状态二维数组,注意这里为了程序求解需要,长度是len+1
    dp = [['' for i in range(len_b+1)] for j in range(len_a+1)]

    for i in range(1, len_a + 1):
        for j in range(1, len_b + 1):
            if a[i-1] == b[j-1]:
                dp[i][j] = dp[i-1][j-1] + a[i-1]
            else:
                lcs_1 = dp[i-1][j]
                lcs_2 = dp[i][j-1]
                if len(lcs_1) > len(lcs_2):
                    dp[i][j] = lcs_1
                else:
                    dp[i][j] = lcs_2
    return dp[len_a][len_b]

print(lcs_dynamic_planning('hello world', 'hero word'))

结果如下:

heo word
    原文作者:算法
    原文地址: https://www.twblogs.net/a/5bd3b0732b717778ac20b34b
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞