专题六:回文子串问题

> 作者:დ旧言~
> 座右铭:松树千年终是朽,槿花一日自为荣。

> 目标:了解什么是记忆化搜索,并且掌握记忆化搜索算法。

> 毒鸡汤:有些事情,总是不明白,所以我不会坚持。早安!

> 专栏选自:动态规划算法_დ旧言~的博客-CSDN博客

> 望小伙伴们点赞👍收藏✨加关注哟💕💕

一、算法讲解

动态规划(Dynamic Programming)算法的核心思想是:将大问题划分为小问题进行解决,从而一步步获取最优解的处理算法:

  • 动态规划算法与分治算法类似,其基本思想也是将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。
  • 与分治法不同的是,适合于用动态规划求解的问题,经分解得到的子问题往往不是互相独立的(即下一个子阶段的求解是建立在上一个子阶段的解的基础上)。

【Tips】动态规划算法解决问题的分类:

  • 计数:有多少种方式走到右下角 / 有多少种方法选出k个数使得和是 sum。
  • 求最大值/最小值:从左上角走到右下角路径的最大数字和最长上升子序列长度。
  • 求存在性:取石子游戏,先手是否必胜 / 能不能取出 k 个数字使得和是 sum。

【Tips】动态规划dp算法一般步骤:

  1. 确定状态表示(dp[ i ] 的含义是什么,来源:1、题目要求;2、经验+题目要求;3、分析问题时发现重复子问题)
  2. 状态转移方程(可求得 dp[ i ] 的数学公式,来源:题目要求+状态表示)
  3. 初始化(dp 表中特别的初始值,保证填 dp 表时不会越界,来源:题目要求+状态表示)
  4. 填表顺序(根据状态转移方程修改 dp[ i ] 的方式,来源:题目要求+状态表示)
  5. 返回值(题目求解的结果,来源:题目要求+状态表示)

二、算法习题

2.1 第一题

题目链接:647. 回文子串 - 力扣(LeetCode)

题目描述:

算法思路:

我们可以先「预处理」⼀下,将所有⼦串「是否回⽂」的信息统计在 dp 表⾥⾯,然后直接在表
⾥⾯统计 true 的个数即可。

1. 状态表⽰:

为了能表⽰出来所有的⼦串,我们可以创建⼀个 n * n 的⼆维 dp 表,只⽤到「上三⻆部分」即可。其中, dp[i][j] 表⽰: s 字符串 [i, j] 的⼦串,是否是回⽂串。

2. 状态转移⽅程:

对于回⽂串,我们⼀般分析⼀个「区间两头」的元素:

  1. 当 s[i] != s[j] 的时候:不可能是回⽂串, dp[i][j] = 0 ;
  2. 当 s[i] == s[j] 的时候:根据⻓度分三种情况讨论: 
  • ⻓度为 1 ,也就是 i == j :此时⼀定是回⽂串, dp[i][j] = true ;
  • ⻓度为 2 ,也就是 i + 1 == j :此时也⼀定是回⽂串, dp[i][j] = true ;
  • ⻓度⼤于 2 ,此时要去看看 [i + 1, j - 1] 区间的⼦串是否回⽂: dp[i][j]= dp[i + 1][j - 1] 。

3. 初始化:

因为我们的状态转移⽅程分析的很细致,因此⽆需初始化。

4. 填表顺序:

根据「状态转移⽅程」,我们需要「从下往上」填写每⼀⾏,每⼀⾏的顺序⽆所谓。

5. 返回值:

根据「状态表⽰和题⽬要求」,我们需要返回 dp 表中 true 的个数。

代码呈现:

class Solution {
public:
    int countSubstrings(string s) 
    {
        // 1. 创建 dp 表
        // 2. 初始化
        // 3. 填表
        // 4. 返回值
        int n = s.size();
        vector<vector<bool>> dp(n, vect
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值