動態規劃-迴文子串c++

5. 最長迴文子串

題目
給定一個字符串 s,找到 s 中最長的迴文子串。你可以假設 s 的最大長度爲 1000。
示例

輸入: "babad"
輸出: "bab"
注意: "aba" 也是一個有效答案。

思路
在這裏插入圖片描述
dp[i][j]數組表示:

字符串s[i\cdots j]s[i⋯j]是否爲迴文子串,如果是,dp[i][j] = truedp[i][j]=true,如果不是,dp[i][j] = falsedp[i][j]=false。
如何我們現在已經知道了dp[i+1][j-1]dp[i+1][j−1]了,那我們如何計算dp[i][j]dp[i][j]呢?通過觀察,我們發現:

  • 如果s[i] == s[j]那麼說明只要dp[i+1][j-1]dp[i+1][j−1]是迴文子串,那麼是dp[i][j]dp[i][j]也就是迴文子串
  • 如果s[i] != s[j] 那麼說明dp[i][j]dp[i][j]必定不是迴文子串。
    在這裏插入圖片描述
  • 因爲不存在i大於j 所以初始化下半三角都是false
  • 遍歷順序從下向上,從左到右
    注:圖片來源
    代碼
class Solution {
public:
    string longestPalindrome(string s) {
        int len  = s.size();
        if(len <= 1) return s;
        vector<vector<bool>> dp(len, vector<bool>(len, false));
        string res = s.substr(0,1);
        for(int i = 0; i < len; i++) dp[i][i]= true;
        for(int i = len-2; i >= 0; i--){
            for(int j = i+1; j < len; j++){
                if(s[i] == s[j]){
                    if(j - i == 1) dp[i][j] = true;
                    else dp[i][j] = dp[i+1][j-1];
                    if(dp[i][j]){
                        if(j - i + 1 > res.size())  res = s.substr(i, j-i+1);
                    }
                }
            }
        }
        return res;
    }
};

516. 最長迴文子序列

題目
給定一個字符串s,找到其中最長的迴文子序列。可以假設s的最大長度爲1000。
示例

輸入:"bbbab"
輸出:4

思路
假設我們現在知道了dp[i+1][j-1]dp[i+1][j−1],我們如何計算dp[i][j]dp[i][j]呢?我們只需要觀察是s[i]s[i] 等不等於s[j]s[j]

  • 當s[i] = s[j]s[i]=s[j],那麼就說明在原先的基礎上又增加了迴文子序列的長度,dp[i][j] = dp[i+1][j-1] + 2;
  • 當s[i]!=s[j],那麼那麼說明s[i]、s[j]s[i]、s[j]至少有一個不在迴文子序列中。那就變成了下圖所示:
    在這裏插入圖片描述
    DP表爲:
    在這裏插入圖片描述
    代碼
class Solution {
public:
    int longestPalindromeSubseq(string s) {
        int len = s.size();
        if(len <= 1) return len;
        int res = 1 ;
        vector<vector<int>>dp(len, vector<int>(len, 0));
        for(int i = 0; i < len; i++) dp[i][i] = 1;
        for(int i = len-2; i >=0; i--){
            for(int j = i+1; j <  len; j++){
                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][len-1];
    }
};

647. 迴文子串

題目
給定一個字符串,你的任務是計算這個字符串中有多少個迴文子串。

具有不同開始位置或結束位置的子串,即使是由相同的字符組成,也會被計爲是不同的子串。
示例

輸入: "abc"
輸出: 3
解釋: 三個迴文子串: "a", "b", "c".

輸入: "aaa"
輸出: 6
說明: 6個迴文子串: "a", "a", "a", "aa", "aa", "aaa".

代碼

class Solution {
public:
    int countSubstrings(string s) {
        //dp[i][j] 表示字符串S i 到j是夠爲迴文
        int len = s.size();
        if(len <= 1) return len;
        vector<vector<bool>> dp(len, vector<bool>(len, false));
        int res = len;
        for(int i = 0; i < len; i++)dp[i][i] = true;
        for(int i = len - 2; i >= 0; i--){
            for(int j = i + 1; j < len; j++){
                if(s[i] == s[j]){
                    if(j - i == 1)dp[i][j] = true;
                     
                    else dp[i][j] = dp[i+1][j-1];
                }
                //這裏有毒吧,爲什麼寫dp[i][j] == ture少兩個結果

                if(dp[i][j])res++;
                     
            }
        }
        return res;
        
            
    }
};

712. 兩個字符串的最小ASCII刪除和

題目
給定兩個字符串s1, s2,找到使兩個字符串相等所需刪除字符的ASCII值的最小和。

示例

輸入: s1 = "sea", s2 = "eat"
輸出: 231
解釋: 在 "sea" 中刪除 "s" 並將 "s" 的值(115)加入總和。
在 "eat" 中刪除 "t" 並將 116 加入總和。
結束時,兩個字符串相等,115 + 116 = 231 就是符合條件的最小和。
注意:

0 < s1.length, s2.length <= 1000。
所有字符串中的字符ASCII值在[97, 122]之間。

代碼

class Solution {
public:
    int minimumDeleteSum(string s1, string s2) {
        
        int leni = s1.size(), lenj = s2.size();
        vector<vector<int>>dp(leni + 1, vector<int>(lenj + 1, 0));
       
        for(int i = 0; i < leni; i++){
            
            for(int j = 0; j < lenj; j++){
                
                if(s1[i] == s2[j]){
                    dp[i+1][j+1] = dp[i][j] + s1[i];
                }else{
                    dp[i+1][j+1] = max(dp[i][j+1], dp[i+1][j]);
                }
                
            }
        }
        int sum = 0;
        for(auto c: s1) sum = sum + (int)c;
        for(auto c: s2) sum = sum + (int)c;
        return sum - 2*dp[leni][lenj];

    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章