1. 程式人生 > 其它 >關於最長迴文串的問題

關於最長迴文串的問題

  • 這兩題都屬於區間dp問題
  • 他不和最長公共子序列一樣,迴文串需要對比區間內首位字元,所以就決定了他只能從中間向兩邊擴散
  • 最後的程式碼會發現:只是狀態轉移的時候賦值問題,子序列不必連續,所以需要去找最大的,而子串連續,只要不相同,這個區間就不是迴文串.

516. 最長迴文子序列

給你一個字串 s ,找出其中最長的迴文子序列,並返回該序列的長度。

子序列定義為:不改變剩餘字元順序的情況下,刪除某些字元或者不刪除任何字元形成的一個序列。

示例 1:
輸入:s = "bbbab"
輸出:4
解釋:一個可能的最長迴文子序列為 "bbbb" 。

解析:兩個字元比較的時候我們需要分別記錄每一個字串的位置,然後去維護dp陣列,直到兩個串遍歷完,
這一題是求一個串的最大回文序列,可以不連續,結果是這個串有,我們化解成子問題就是從最開始的子串長度為一開始,一步一步增加,屬於區間dp,搞清楚轉移方程和初始化後,看一看原始陣列,然後在決定怎麼遍歷.

class Solution {
public:
    //區間dp
    int longestPalindromeSubseq(string s) {
        int len = s.size();
        vector<vector<int>> dp(len + 1, vector<int>(len + 1, 0));
        for(int i = 0; i < len; i++) {
            dp[i][i] = 1;
        }
        for(int i = 1; i < len; i++) {
            for(int j = i - 1; j >= 0; j--) {
                if(s[i] == s[j]) {
                    dp[i][j] = dp[i - 1][j + 1] + 2;
                }else {
                    dp[i][j] = max(dp[i][j + 1], dp[i - 1][j]);
                }
            }
        }
        return dp[len - 1][0];
    }
};

5. 最長迴文子串

給你一個字串 s,找到 s 中最長的迴文子串。

示例 1:
輸入:s = "babad"
輸出:"bab"
解釋:"aba" 同樣是符合題意的答案。

class Solution {
public:
    string longestPalindrome(string s) {
        int len = s.size();
        vector<vector<int>> dp(len + 1, vector<int>(len + 1, 0));
        for(int i = 0; i < len; i++) {
            dp[i][i] = 1;
        }
        int ans = 0;
        int start = 0,end = 0;
        for(int i = 1; i < len; i++) {
            for(int j = i - 1; j >= 0; j--) {
                if(s[i] == s[j]) {
                    if(i - j == 1) dp[i][j] = 1;
                    else dp[i][j] = dp[i - 1][j + 1];
                }
                if (dp[i][j] && ans < (i - j + 1)) {
                    ans = (i - j + 1);
                    start = j,end = i;
                }
            }
        }
        return s.substr(start, end - start + 1);
    }
};