leetcode 516. 最长回文子序列
题目描述
给定一个字符串s
,找到其中最长的回文子序列
示例 1: 输入:
"bbbab"
输出:
4
一个可能的最长回文子序列为 “bbbb”。
# -*- coding: utf-8 -*-
# @Time : 2019-10-11 11:58
# @Author : Jayce Wong
# @ProjectName : job
# @FileName : longestPalindromicSubsequence.py
# @Blog : https://sysujayce.github.io/
# @Github : https://github.com/SysuJayce
class Solution:
"""
dp[i][j]表示s[i: j + 1]的最长回文子序列长度
若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[i][i] = 1,因为s[i: i + 1]总是一个回文字符串,长度为1
"""
def longestPalindromeSubseq(self, s: str) :
if len(s) < 2 or s == s[:: -1]:
return len(s)
dp = [[0] * len(s) for _ in range(len(s))]
for j in range(len(s)): # col
# 逐列填充矩阵
dp[j][j] = 1
for i in reversed(range(j)): # row
# 从对角线开始往上填充
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])
# 最后矩阵的右上角就是所求的长度
return dp[0][-1], self.findPalindrome(dp, s)
def findPalindrome(self, dp, s):
"""
要从已经计算好的状态矩阵中找出所有的最长公共子序列,我们需要关注的是当出现向上和向左都可以
的时候,需要保持方向的一致,向上就一直向上,向左就一直向左,否则会出现问题。
"""
rows, cols = len(dp), len(dp[0])
i, j = 0, cols - 1
ans = ''
while i < rows and j >= 0:
# 因为我们是反向查找的,所以加到前面去
if dp[i][j] == 0 or dp[i][j] > dp[i + 1][j]:
ans = s[i] + ans
i += 1
j -= 1
else:
i += 1
return ans
def main():
solution = Solution()
s = 'axbdba'
length, palindrome = solution.longestPalindromeSubseq(s)
print(length)
print(palindrome)
if __name__ == '__main__':
main()
- 原文作者:Jayce
- 原文链接:https://sysujayce.github.io/posts/longestpalindromicsubsequence/
- 版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。