动态规划预处理+动态规划求解 132. 分割回文串 II

132. 分割回文串 II

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

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

示例:

输入: "aab"
输出: 1

解释: 进行一次分割就可将 s 分割成 [“aa”,“b”] 这样两个回文子串。

动态规划(中心拓展)预处理+dfs求解(超时)
先动态规划或中心拓展法,得到每两个的位置之间是否为回文字符串;
然后尝试从每个位置切,得到答案——超时;

class Solution {
public:
    int minCut(string s) {
        //以i为终点的回文子串长度是多少
        n=s.size();
        dp.resize(n,vector<bool>(n,0));
        for(int i=0;i<n;i++)
        {
            fromcenter(s,i,i);
            fromcenter(s,i,i+1);
        }
        mincnt=INT_MAX;
        dfs(0,0);
        return mincnt;
    }
private:
    vector<vector<bool>> dp;
 
    int mincnt;
    int n;
    void fromcenter(string s,int a,int b)
    {
        while(a>=0&&b<n&&s[a]==s[b]){
            dp[a][b]=1;
            a--;b++;
        }

        return;
    }
    void dfs(int i,int cnt){
        if(i==n) {
                mincnt=min(cnt-1,mincnt);
                return;
        }
        for(int t=i;t<n;t++){
            if(dp[i][t])
            dfs(t+1,cnt+1);
        }
        return;
    }

};

动态规划预处理(中心拓展)+动态规划求解
得到每两个位置是否为回文字符串;
进行动态规划:
res[i]为前i个字符需要切的刀数;
res[i+1]最大为res[i]+1;
遍历0~i,若有dp[j+1][i] 则res[j]+1与res[i]比较,取小值即可;
时间复杂度O(N*N);

class Solution {
public:
    int minCut(string s) {
        n=s.size();
        dp.resize(n,vector<bool>(n,0));
        for(int i=0;i<n;i++){
            fromcenter(s,i,i);
            fromcenter(s,i,i+1);
        }
        res.resize(n,0);
        for(int i=1;i<n;i++)
        {
            if(dp[0][i]) res[i]=0; //不用分割
            else{   //要分割
                res[i]=res[i-1]+1;//分割最大次数
                for(int j=0;j<i-1;j++)
                    if(dp[j+1][i])res[i]=min(res[j]+1,res[i]);
                    //j后面一个到i              j之前的刀数+1刀
            }
        }
        return res[n-1];
    }
private:
    vector<vector<bool>> dp;
    vector<int> res;
    int n;
    void fromcenter(string s,int a,int b){
        while(a>=0&&b<n&&s[a]==s[b])
            dp[a--][b++]=1;
        }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值