【LeetCode刷題(困難程度)】132. 分割回文串 II

讀研的小狗子發表於2020-10-15

給定一個字串 s,將 s 分割成一些子串,使每個子串都是迴文串。

返回符合要求的最少分割次數。

示例:

輸入: “aab”
輸出: 1
解釋: 進行一次分割就可將 s 分割成 [“aa”,“b”] 這樣兩個迴文子串。

來源:力扣(LeetCode)
連結:https://leetcode-cn.com/problems/palindrome-partitioning-ii
著作權歸領釦網路所有。商業轉載請聯絡官方授權,非商業轉載請註明出處。

思路:使用動態規劃。

從最優策略的前提下關注最後一段迴文串。設為:S[j...N-1],那麼要知道整個字串能劃分成最少則還需要知道Sj個字元[0..j-1]最少可以劃分成幾個迴文串。(劃分出了子問題)

初始條件:f[0] = 00個字元可以劃分成0個迴文串個數。
f[i]表示前i個字元S[0..i-1]最少可以劃分成的迴文串個數。
則轉移方程:
在這裡插入圖片描述
判斷迴文串:採用從中心向兩邊擴張的方法。(優化的話可以用馬拉車)

class Solution {
public:
    int minCut(string s) {
        int n = s.size();
        if(n == 0)
            return 0;
        vector<vector<bool>> isPalin(n,vector<bool>(n,false));
        isPalin = calcPalin(s);
        vector<int>f(n+1,0);
        f[0] = 0;

        for(int i = 1;i <= n;++i)
        {
            f[i] = INT_MAX;
            for(int j = 0; j < i;++j)
            {
                if(isPalin[j][i - 1])//只要j到i-1是迴文串 就更新
                {
                    f[i] = min(f[i],f[j] + 1);
                }
            }
        }
        return f[n] - 1;//題目中求的是分割字串次數 我們求出了能分出多少個字串
        	//那麼次數就是字串個數減1
    }
private:
    vector<vector<bool>> calcPalin(const string& s)
    {
        int n = s.size();
        vector<vector<bool>>f(n,vector<bool>(n,false));

        int i;
        int j;

        //奇數情況
        for(int c = 0; c < n; ++c)
        {
            i = j = c;

            //生成迴文串法檢測迴文串
            while(i >= 0&&j < n && s[i] == s[j])
            {
                f[i][j] = true;
                --i;
                ++j;
            }
        }

        //偶數情況
        for(int c = 0;c < n - 1;++c)
        {
            i = c;
            j = c + 1;

            while(i >= 0 && j < n && s[i] == s[j])
            {
                f[i][j] = true;
                --i;
                ++j;
            }
        }
        return f;
    }
};

相關文章