132. 分割回文串 II

题目描述

给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串。返回符合要求的最少分割次数。
示例:
输入: "aab"
输出: 1
解释: 进行一次分割就可将 s 分割成 ["aa","b"] 这样两个回文子串。

方法1

暴力动态规划,LeetCode耗时40ms,内存消耗9.3MB。

class Solution {
public:
	int minCut(string s)
    {   
    	int n = s.length();
    	if(n == 0 || n == 1)
    		return 0;
        vector<int> dp(n);
        for(int i=0;i<n;i++)
           dp[i] = i;
       //这里使用了两个额外的结构来保存信息,其中一个是主要的,
       //一个是辅助的
        vector<vector<bool>> isPalindrome(n,vector<bool>(n,false));
        for(int i = 0;i < n;i++)
        {
            for(int j = 0;j <= i;j++)
            {  
                if(s[j] == s[i] && (i-j<=2 || isPalindrome[j+1][i-1]))
                {
                	isPalindrome[j][i] = true;
                	if(j == 0)
                		dp[i]=0;
                    else 
                    	dp[i] = min(dp[i],1+dp[j-1]);
                }   
            }
        }
        return dp[n-1];
    }
};

方法2

中心扩展法更新dp的值

class Solution {
public:
    int minCut(string s) {

        int n = s.size();
        //dp[i]含义为s[0,i-1]的最小分割次数
        //由于这里为了递推的需要,需要使用长度为0时的最小分割次数
        //所以,这里的动态规划数组的下标含义为长度
        vector<int> dp(n+1, 0);
        for(int i = 0; i <= n; i++) 
            //这里根据递推公式合理的将dp[0]初始化为-1
            dp[i] = i-1;
        //每一次对当前位置i的中心扩展,只会更新这个扩展的右边界处的dp值,不影响i的左侧已经确定的dp值,
        //i处的dp的最终值,在i处如果单独奇数扩展分割后自己构成右边界同i处已有
        //的dp值比较后确定。起始时,可以看成i=0的左边处的情况为dp[0]=-1已经确定了
        for(int i = 0; i < n; i++)//i为元素下标
        {      //j为相对于i的偏移量
            for(int j = 0; i-j >= 0 && i+j < n && s[i-j]==s[i+j] ; j++) //奇数 length palindrome
                dp[i+j+1] = min(dp[i+j+1],1+dp[i-j]);
            for(int j = 0; i-j >= 0 && i+1+j < n && s[i-j] == s[i+1+j]; j++) //偶数 length palindrome
                dp[i+1+j+1] = min(dp[i+1+j+1],1+dp[i-j]);
        }
        return dp[n];
    }
};

posted on 2021-05-02 12:25  朴素贝叶斯  阅读(30)  评论(0编辑  收藏  举报

导航