返回
力扣:动态规划之最长回文子序列
闲谈
2023-12-16 18:01:53
动态规划的登堂入室
动态规划,一个听起来很抽象的名词,却在算法和程序设计领域有着举足轻重的地位。动态规划是一种将复杂问题分解为一系列小问题的算法策略,通过求解这些小问题,逐步推导出最终的解决方案。
动态规划的本质是利用子问题的最优解来构造整个问题的最优解。也就是说,如果我们能够找到问题中的子问题,并且这些子问题的最优解能够帮助我们找到整个问题的最优解,那么我们就可以通过动态规划来解决这个问题。
动态规划解决最长回文子序列问题
最长回文子序列问题是一个经典的动态规划问题。给定一个字符串,我们需要找到这个字符串中最长的回文子序列。回文子序列是指一个字符串的子序列,当我们从左到右或从右到左读这个子序列时,它都是一样的。
例如,字符串 "abba"
的最长回文子序列是 "abba"
本身,因为 "abba"
从左到右或从右到左读都是一样的。
动态规划算法步骤
-
定义子问题: 对于一个长度为
n
的字符串s
,我们定义子问题dp[i][j]
为从s[i]
到s[j]
的最长回文子序列的长度。其中,0 ≤ i ≤ j ≤ n-1
。 -
初始化子问题: 对于所有
i
和j
,如果i > j
,那么dp[i][j]
为0
。如果i = j
,那么dp[i][j]
为1
。 -
递推公式: 对于所有
i
和j
,如果i < j
,那么dp[i][j]
可以由以下公式计算:- 如果
s[i] = s[j]
,那么dp[i][j] = dp[i+1][j-1] + 2
。 - 如果
s[i] ≠ s[j]
,那么dp[i][j] = max(dp[i+1][j], dp[i][j-1])
。
- 如果
-
计算最终解: 最长回文子序列的长度为
dp[0][n-1]
。
代码实现
def longest_palindrome_subsequence(s):
"""
Returns the longest palindrome subsequence of the given string.
Args:
s (str): The string to find the longest palindrome subsequence of.
Returns:
str: The longest palindrome subsequence of the given string.
"""
# Create a 2D array to store the lengths of the longest palindrome subsequences
# of all substrings of the given string.
dp = [[0 for _ in range(len(s))] for _ in range(len(s))]
# Initialize the diagonal elements of the array to 1, since a single character
# is always a palindrome subsequence of itself.
for i in range(len(s)):
dp[i][i] = 1
# Fill the rest of the array using the遞推公式.
for i in range(len(s)-1, -1, -1):
for j in range(i+1, len(s)):
if s[i] == s[j]:
dp[i][j] = dp[i+1][j-1] + 2
else:
dp[i][j] = max(dp[i+1][j], dp[i][j-1])
# Find the longest palindrome subsequence by finding the maximum value in the
# last row of the array.
max_length = 0
for i in range(len(s)):
if dp[i][len(s)-1] > max_length:
max_length = dp[i][len(s)-1]
# Construct the longest palindrome subsequence by backtracking through the array.
longest_palindrome_subsequence = ""
i = 0
j = len(s) - 1
while i <= j:
if s[i] == s[j]:
longest_palindrome_subsequence += s[i]
i += 1
j -= 1
elif dp[i+1][j] > dp[i][j-1]:
i += 1
else:
j -= 1
return longest_palindrome_subsequence
# Example usage
s = "abba"
print(longest_palindrome_subsequence(s)) # Output: "abba"