【LeetCode-132】分割回文串 II

问题

给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是回文。

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

示例

输入: s = "aab"
输出: 1
解释: 只需一次分割就可将 s 分割成 ["aa","b"] 这样两个回文子串。

解答

class Solution {
public:
    int minCut(string s) {
        int n = s.size();
        bool dp[n][n]; memset(dp, 1, sizeof(dp));
        int f[n]; // f[i]表示以i结尾的字符串最少分割次数
        for (int i = n - 1; i >= 0; i--)
            for (int j = i + 1; j < n; j++)
                dp[i][j] = (s[i] == s[j]) && dp[i + 1][j - 1];
        for (int j = 0; j < n; j++) {
            if (dp[0][j]) f[j] = 0; // 是内层循环中i=0时的特例,边界
            else {
                f[j] = f[j - 1] + 1; // 以s[j]单独分隔作为初始化
                for (int i = 1; i < j; i++) // 遍历[i, j]能够形成回文串的分割次数,取其中最小
                    if (dp[i][j]) f[j] = min(f[j], f[i - 1] + 1);
            }
        }
        return f[n - 1];
    }
};

重点思路

这道题还是有点麻烦。使用动态规划预处理回文串在之前的文章已经讲过具体操作。本题的重难点在于如何使用动态规划,使用上一状态的最小分割次数推导下一状态的最小分割次数。

首先需要有一个大致的思路。首先分析一般情况,我们要遍历上一状态中所有元素,设当前遍历到角标i,若[i, j]这一段字符串满足回文要求,则可以以i元素前为分割点,此时切割次数需要f[j] = f[i - 1] + 1,遍历所有元素取最小值,此时我们可以得到状态转移方程为if (满足要求) f[j] = min(f[j], f[i - 1] + 1)。然后分析边界条件,由状态方程可以得到,i = 0时会越界。当i = 0时,此时直接判断[0, j]这一段字符串是否为回文串。分析状态方程可以得知,每个f[i]都需要初始化,这里的做法是每个单独初始化。

posted @ 2021-03-09 15:57  tmpUser  阅读(36)  评论(0编辑  收藏  举报