动态规划-序列型动态规划

1 回文子串

# Given a string s, return the longest palindromic substring in s. 
# 
#  
#  Example 1: 
# 
#  
# Input: s = "babad"
# Output: "bab"
# Explanation: "aba" is also a valid answer.
#  
# 
#  Example 2: 
# 
#  
# Input: s = "cbbd"
# Output: "bb"
#  
# 
#  
#  Constraints: 
# 
#  
#  1 <= s.length <= 1000 
#  s consist of only digits and English letters. 
#  
import pandas as pd

# leetcode submit region begin(Prohibit modification and deletion)
class Solution:
    def longestPalindrome(self, s: str) -> str:
        # i和j分别存储起始点和终点,数值存长度的大小
        # f[i][j] = f[i+1][j-1] + 2 if s[i-1] == s[j-1] else f[i][j] = 0
        n = len(s)
        f = [[0] * (n) for _ in range(n)]
        max_len = 0
        x = -1
        y = -1
        for i in range(n - 1, -1, -1):
            for j in range(i, n, 1):
                if s[i] == s[j]:
                	# 初始化,回文子串的长度是奇数
                    if i == j:
                        f[i][j] = 1
                    else:
                    	# 初始化,回文子串的长度是偶数
                        if i + 1 > j - 1:
                            f[i][j] = 2
                        # 过程更新,确保转移之前子串是回文串
                        elif f[i + 1][j - 1]:
                            f[i][j] = f[i + 1][j - 1] + 2
                else:
                    f[i][j] = 0
                if f[i][j] > max_len:
                    x = i
                    y = j
                    max_len = f[i][j]
        return s[x:y + 1]


# leetcode submit region end(Prohibit modification and deletion)

if __name__ == '__main__':
    so = Solution()
    s = "babad"
    res = so.longestPalindrome(s)
    print(res)

1.1 解题思路

  • 确定f[i][j]的含义,表示以i子串开始,j子串结束,即f[i][j]回文子串的长度。
  • 确定动态转移方程,动态转移方程的核心f[i][j] = f[i + 1][j - 1] + 2 if s[i] == s[j]
  • 确定初始化条件,初始化条件包括奇数和偶数两种情况。
  • 确定遍历的顺序,i依赖i+1, j依赖j-1,所以对i进行倒序遍历,对j进行正序遍历

2 回文子序列

# Given a string s, find the longest palindromic subsequence's length in s. 
# 
#  A subsequence is a sequence that can be derived from another sequence by 
# deleting some or no elements without changing the order of the remaining elements. 
# 
#  
#  Example 1: 
# 
#  
# Input: s = "bbbab"
# Output: 4
# Explanation: One possible longest palindromic subsequence is "bbbb".
#  
# 
#  Example 2: 
# 
#  
# Input: s = "cbbd"
# Output: 2
# Explanation: One possible longest palindromic subsequence is "bb".
#  
# 
#  
#  Constraints: 
# 
#  
#  1 <= s.length <= 1000 
#  s consists only of lowercase English letters. 
#  


# leetcode submit region begin(Prohibit modification and deletion)
class Solution:
    def longestPalindromeSubseq(self, s: str) -> int:
        # f[i][j] = f[i+1][j-1] + 2 if s[i]==s[j]
        # f[i][j] = max(f[i][j-1], f[i-1][j]) if s[i] != s[j]
        l = len(s)
        max_len = 0
        f = [[0] * l for _ in range(l)]
        for i in range(l - 1, -1, -1):
            for j in range(i, l, 1):
                if s[i] == s[j]:
                    if i == j:
                        f[i][j] = 1
                    else:
                        if i + 1 > j - 1:
                            f[i][j] = 2
                        else:
                            f[i][j] = f[i + 1][j - 1] + 2
                else:
                    f[i][j] = max(f[i][j - 1], f[i + 1][j])
                if f[i][j] > max_len:
                    max_len = f[i][j]
        return max_len


# leetcode submit region end(Prohibit modification and deletion)


if __name__ == '__main__':
    so = Solution()
    s = "bbbab"
    res = so.longestPalindromeSubseq(s)
    print(res)

2.1 解题思路

  • 回文子串和回文子序列关键差异在于动态转移方程不相等情况的处理,回文子串如果不相等,f[i][j] = 0,回文子序列则是f[i][j] = max(f[i][j - 1], f[i + 1][j])

你可能感兴趣的:(数据结构,动态规划,算法)