132.分割回文串II 详解,看不懂你找我!!!

题目描述

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

返回符合要求的 最少分割次数 。
输入:s = “aab”
输出:1
解释:只需一次分割就可将 s 分割成 [“aa”,“b”] 这样两个回文子串。
输入:s = “a”
输出:0

解题分析

1.递归尝试

定义函数 f(string str,int i), 返回的结果是字符串str 从下标i开始到字符串末尾的最小分割次数,那么主函数即f(str,0)。

我们以 aabaca 为例分析,该字符串长度 n = 6
我们要求的结果是f(0), 此时我们可以分析f(0) 有哪些可能性:

  1. 从0位置分割,str[0…0] 为a 是回文串,这种可能性结果为 1+ f(1)
  2. 从1位置分割,str[0…1] 为 aa 是回文串, 这种可能性结果为 1 + f(2)
  3. 从2位置分割,str[0…2]: aab 不是回文串,不符合要求
  4. 从 3 位置分割,str[0…3]: aaba 也不是回文串,不符合要求
  5. 。。。。

因此可以写出下面的伪代码:

// 返回 [i...n-1] 的 最小分割次数
int f(int i){
	if(str[i...n-1] 是回文串){
		return 0;
	}
	int res = INT_MAX;
	for(int j = i;j<n-1;++j){
		if(str[i..j] 是回文串){
			res = min(res,1+f(j+1))
		}
	}
	return res;
}

2.动态规划

由上述暴力递归得知,我们当前的结果 f(i) , 可能依赖后续的每一个结果, 因此,我们定义 dp[i] 表示str[i…n-1] 的最少分割次数。

自然的,可以得出状态转移方程:

if(str[i..j] 是回文串){
	dp[i] = min(dp[i],dp[j+1]+1);
}

因此,求解dp 数组我们需要从后往前求,最后结果为 dp[0]。

此时我们还剩下最后一个问题,即判断 str[i…j] 是否是回文,这是一个典型的动态规划,我们定义 isH[i][j] 表示str[i][j] 是否回文,
则状态转移方程为:

if(str[i] == str[j]){
	isH[i][j] = isH[i+1][j-1];
}

至此,完整的代码如下:

int minCut(string s) {
        int n = s.size();
        // 1. first judge str[l...r]
        vector<vector<int>> isH(n,vector<int>(n,0));
        for(int i=0;i<n-1;++i){
            isH[i][i] = 1;
            if(s[i] == s[i+1]){
                isH[i][i+1] = 1;
            }
        }
        isH[n-1][n-1] = 1;
        for(int i=n-3;i>=0;i--){
            for(int j= i+2;j<n;++j){
                if(s[i] == s[j]){
                    isH[i][j] = isH[i+1][j-1];
                }
            }
        }

        // dp[i]  result of str[i...n-1] 
        vector<int> dp(n,INT_MAX);
        dp[n-1] = 0;
        for(int i=n-2;i>=0;i--){
            if(isH[i][n-1] != 1){
                for(int j=i;j<n-1;++j){
                    if(isH[i][j]){ // 判断str[i..j] 是否回文
                        dp[i] = min(dp[i],dp[j+1]+1);
                    }
                }       
            }else{
                dp[i] = 0;
            }
        }
       return dp[0];
    }

提交 通过。


如果有改进的地方,还希望多多指教,谢谢。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值