程式碼隨想錄演算法訓練營第49天 | 動態規劃總結

哆啦**發表於2024-07-28

程式碼隨想錄演算法訓練營第天 |

647.迴文子串
https://leetcode.cn/problems/palindromic-substrings/description/
程式碼隨想錄
https://programmercarl.com/0647.迴文子串.html#思路
516.最長迴文子序列
https://leetcode.cn/problems/longest-palindromic-subsequence/
程式碼隨想錄
https://programmercarl.com/0516.最長迴文子序列.html#思路

647. 迴文子串

  • dp[i][j]的定義
    • 布林型別的dp[i][j]:表示區間範圍[i,j] (注意是左閉右閉)的子串是否是迴文子串,如果是dp[i][j]為true,否則為false。
  • 遞推公式
    • s[i]!=s[j] 說明兩端不同 一定不是 dp[i][j]= Flase
    • s[i]==s[j]:分類討論情況
      1. i和j相同 同一個字串一定是
      2. i-j==1 差一個也是迴文字串
      3. i-1>1 如果dp[i+1][j-1]是迴文字串 這個也一定是
  • 初始化:全部為false
  • 遍歷順序
    • 遍歷順序由上面的依賴條件決定;這裡dp[i+1][j-1]得到dp[i][j]。所以從左下向右上遍歷
點選檢視程式碼
class Solution:
    def countSubstrings(self, s: str) -> int:
        dp = [[False]*len(s) for _ in range(len(s))]
        res = 0
        for i in range(len(s)-1,-1,-1):
            for j in range(i,len(s)):
                if s[i]==s[j]:
                    if abs(i-j)<2:
                        dp[i][j] = True
                        res = res+1
                    else:
                        if dp[i+1][j-1]:
                            dp[i][j] = True
                            res = res+1
        return res

516. 最長迴文子序列

  • 迴文子序列和迴文序列的區別:如果兩個序列不一樣的話,選取左右兩側的最大值;
  • 即使內部的子序列不是迴文序列也可以;只需要在相同時增加長度即可;
點選檢視程式碼
class Solution:
    def longestPalindromeSubseq(self, s: str) -> int:
        dp = [[0]*len(s) for _ in range(len(s))]
        max_length = 0
        for i in range(len(s)-1,-1,-1):
            for j in range(i,len(s)):
                if s[i]==s[j]:
                    if i==j:
                        dp[i][j] = 1
                    else:
                        dp[i][j] = dp[i+1][j-1]+2
                else:
                    dp[i][j] = max(dp[i+1][j],dp[i][j-1])
                if dp[i][j]>max_length:
                    max_length = dp[i][j]
        # print(np.array(dp))
        return max_length

相關文章