【算法挨揍日记】day35——1745. 分割回文串 IV、132. 分割回文串 II

1745. 分割回文串 IV 

1745. 分割回文串 IV

题目描述:

给你一个字符串 s ,如果可以将它分割成三个 非空 回文子字符串,那么返回 true ,否则返回 false 。

当一个字符串正着读和反着读是一模一样的,就称其为 回文字符串 。

解题思路:

在647题的基础上, 我们从后向前遍历dp表中所有为true的情况,看否可以将他们分为3段

解题代码:

class Solution {
public:
    bool checkPartitioning(string s) {
        int n=s.size();
        vector<vector<bool>>dp(n,vector(n,false));
        for(int i=n-1;i>=0;i--)
        {
            for(int j=i;j<n;j++)
            {
                if(s[i]==s[j])
                {
                    if(i==j)dp[i][j]=true;
                    else if(i+1==j)dp[i][j]=true;
                    else dp[i][j]=dp[i+1][j-1];
                }
            }
        }
       for(int i=n-1;i>=0;i--)
       {
           if(dp[i][n-1]==true)
           {
               for(int begin=i-1;begin>0;begin--)
               {
                   if(dp[begin][i-1]==true&&dp[0][begin-1]==true)
                   return true;
               }
           }
       }
       return false;

    }
};

 132. 分割回文串 II

132. 分割回文串 II

题目描述:

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

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

 解题思路:
 

算法思路:
1. 状态表⽰:
根据「经验」,继续尝试⽤ i 位置为结尾,定义状态表⽰,看看能否解决问题:
dp[i] 表⽰: s [0, i] 区间上的字符串,最少分割的次数。
2. 状态转移⽅程:
状态转移⽅程⼀般都是根据「最后⼀个位置」的信息来分析:设 0 <= j <= i ,那么我们可以
根据 j ~ i 位置上的⼦串是否是回⽂串分成下⾯两类:
i. [j ,i] 位置上的⼦串能够构成⼀个回⽂串,那么 dp[i] 就等于 [0, j - 1]
间上最少回⽂串的个数 + 1,即 dp[i] = dp[j - 1] + 1
ii. [j ,i] 位置上的⼦串不能构成⼀个回⽂串,此时 j 位置就不⽤考虑。
由于我们要的是最⼩值,因此应该循环遍历⼀遍 j 的取值,拿到⾥⾯的最⼩值即可。
优化:我们在状态转移⽅程⾥⾯分析到,要能够快速判读字符串⾥⾯的⼦串是否回⽂。因此,我们
可以先处理⼀个 dp 表,⾥⾯保存所有⼦串是否回⽂的信息。
3. 初始化:
观察「状态转移⽅程」,我们会⽤到 j - 1 位置的值。我们可以思考⼀下当 j == 0 的时候,
表⽰的区间就是 [0, i] 。如果 [0, i] 区间上的字符串已经是回⽂串了,最⼩的回⽂串就是
1 了, j 往后的值就不⽤遍历了。
因此,我们可以在循环遍历 j 的值之前处理 j == 0 的情况,然后 j 1 开始循环。
但是,为了防⽌求 min 操作时, 0 ⼲扰结果。我们先把表⾥⾯的值初始化为「⽆穷⼤」。
4. 填表顺序:
毫⽆疑问是「从左往右」。
5. 返回值:
根据「状态表⽰」,应该返回 dp[n - 1]

解题代码:

class Solution {
public:
    int minCut(string s) {
        int n=s.size();
        vector<vector<bool>>dp(n,vector(n,false));
        for(int i=n-1;i>=0;i--)
        {
            for(int j=i;j<n;j++)
            {
                if(s[i]==s[j])
                {
                    if(i==j)dp[i][j]=true;
                    else if(i+1==j)dp[i][j]=true;
                    else dp[i][j]=dp[i+1][j-1];
                }
            }
        }

       vector<int>f(n,INT_MAX);
       for(int i=0;i<n;i++)
       {
           if(dp[0][i]==true)
           f[i]=0;
           else
           {
               for(int j=i;j>0;j--)
               {
                   if(dp[j][i]==true)
                    f[i]=min(f[i],f[j-1]+1);
               }
           }
       }
        return f[n-1];
    }
};

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

学IT的小卢

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值