Leetcode 132. 分割回文串 II C++

Leetcode 132. 分割回文串 II

题目

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

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

测试样例

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

题解

动态规划
我们先确定那一段字符串是回文串,这里可以用到第一段动态规划
令circle[i][j]表示字符串s[i]~s[j]是一个回文串,显然,当s[i] == s[j],我们只需要看s[i+1] ~ s[j-1]是不是回文串,即circle[i][j] = circle[i+1][j-1]。当s[i] != s[j],circle[i][j]显然为false
我们根据上面的情况,可以知道,我们在长度大于等于3的时候才能用到上面的转移方程,那我们只需要考虑初始条件,即长度为1、2的字符串。显然,长度为1的字符串是回文串,长度为2的字符串则需要判断两个字符是否相等了。
我们现在已经知道了那一段字符串是回文串了,我们现在再考虑分割最少次。这里就用到了第二段动态规划
令dp[i]表示将s的前i个字符分割为回文串的最小分割次数,显然我们需要往前找到能分割的地方j,然后分割次数就是dp[j]+1。详细过程见代码

int minCut(string s) {
        int i=0,j,n=s.length();
        vector<int> dp(n+1,0);
        vector<vector<bool>> circle(n,vector<bool>(n,false));
        for(int i=0; i<n; i++){
            circle[i][i] = true;
            if(i!=0 && s[i-1]==s[i])
                circle[i-1][i] = true;
        }
        for(int len=3; len<=n; len++){
            for(int i=0; i<=n-len; i++){
                int j=i+len-1;
                if(s[i] == s[j])
                    circle[i][j] = circle[i+1][j-1];
            }
        }
        dp[0]=-1;
        for(int i=1; i<=n; i++){
            dp[i] = dp[i-1]+1;
            for(j=0; j<i; j++){
                if(circle[j][i-1])		//当前位置我们可以作为最后一段回文子串
                    dp[i] = min(dp[j]+1,dp[i]);
            }
        }
        return dp[n];
    }

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/palindrome-partitioning-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

你可能感兴趣的:(Leetcode 132. 分割回文串 II C++)