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

给定一个字符串 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;
    }
};

猜你喜欢

转载自blog.csdn.net/qq_33197518/article/details/109090125