算法學習-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