【动态规划】回文串问题

在这里插入图片描述

点赞👍👍收藏🌟🌟关注💖💖
你的支持是对我最大的鼓励,我们一起努力吧!😃😃

1.回文子串

题目链接:647. 回文子串

题目分析:

在这里插入图片描述

子串和子数组是一样的。

具有不同开始位置或者结束位置的子串,即使是由相同的字符组成,也会被视作不同的子串。

算法原理:

对于这道题相比于动态规划,中心扩展算法和马拉车算法更优秀。

中心扩展算法:时间复杂度O(N^2),空间复杂度O(1)
马拉车算法:时间复杂度O(N),空间复杂度O(N)
动态规划:时间复杂度O(N^2), 空间复杂度O(N^2)

动态规划虽然这里不是最优解,但是它的思想可以让有些回文串的困难题变成容易题。

能够将所有的子串是否是回文的信息,保存在 dp 表里面

1.状态表示

既然要把所有子串都放在dp表里面,一个一维dp肯定不够,

在这里插入图片描述
dp[i][j] 表示 s 字符串 [i, j] 的子串,是否是回文串

2.状态转移方程

判断 i - > j 是否是回文串,必须首先 i 位置 和 j 位置字符是相等的,如果都不相等,即使里面在好, i - > j 子串也不回文串

在这里插入图片描述

i 位置 和 j 位置字符相等,这里分三种情况:
i == j , ij同一个位置 是回文子串
i + 1 == j ,ij相邻 是回文子串
还有就是 i -> j 中间有别的字符,那就看 i + 1 位置 到 j - 1 位置的子串是否是回文子串,而i + 1 位 到 j - 1 是否是回文子串就在dp[i + 1][j - 1]
在这里插入图片描述

3.初始化

会发生越界的就只有 dp[i + 1][j -1],但是它会发生越界情况都已经在 i == j,i + 1 < j 这两种情况考虑到了。

在这里插入图片描述

4.填表顺序

dp[i][j] 可能会用到 dp[i + 1][j -1],所以从下往上填。

在这里插入图片描述

5.返回值

统计dp表中true的个数。

class Solution {
   
   
public:
    int countSubstrings(string s) {
   
   
        // 1.创建 dp 表
        // 2.初始化
        // 3.填表
        // 4.返回值

        int n = s.size();
        vector<vector<bool>> dp(n, vector<bool>(n));
        int ret = 0;
        for(int i = n - 1; i >= 0; --i)
        {
   
   
            for(int j = i; j < n; ++j)
            {
   
   
                if(s[i] == s[j])
                {
   
   
                    dp[i][j] = i + 1 < j ? dp[i + 1][j - 1] : true;
                }
                
                if(dp[i][j]) ret += 1; // 统计个数
            }
        }
        return ret;

    }
};

2.最长回文子串

题目链接: 5. 最长回文子串

题目描述:

在这里插入图片描述

算法原理:

如果上面那道题搞懂了,这道题完全直接就去做就行了。可以这样做:

判断子串是否是回文 —> 用 dp 表,统计所有子串是否是回文的信息 —> 根据 dp 表的起始位置得到我们想要的结果。

起始位置 i,回文串结束位置 j,回文串长度 j - 1 + 1

1.状态表示

dp[i][j] 表示 s 字符串 [i, j] 的子串,是否是回文串

2.状态转移方程

在这里插入图片描述

3.初始化

无需初始化,当用到 dp[i+1][j-1] 是有条件的,当 i + 1 < j才会用,此时不会越界。只有当 i == j,i + 1 == j 才会越界,但是我们已经特殊处理过了。

4.填表顺序

dp[i][j] 可能会用到 dp[i + 1][j -1],所以从下往上填。

在这里插入图片描述

5.返回值

dp 里面值为 true 的情况下,长度最大的子串的起始位置以及长度

class Solution {
   
   
public:
    string longestPalindrome(string s) {
   
   
        //1.创建 dp 表
        //2.初始化
        //3.填表
        //4.返回值

        int n = s.size(
评论 103
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值