(M)Dynamic Programming:647. Palindromic Substrings

本文介绍了一种计算字符串中回文子串数量的方法,使用动态规划算法,并通过一维和二维两种方式实现,详细解释了算法原理及其实现过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这个题我写的有点麻烦,又是在string下标上调了半天。感觉做这种编程题尽量还是避免这种复杂的下标变换,真的很容易出错。我的思路是,定义一个vector<int> dp(n, 0),从后往前遍历字符串,比如,遍历字符串第i个位置s[i],只需要求以s[i]开头的回文子串个数ni。那么s[i, s.size()-1]这个子串的所有回文子串就是ni + dp[i + 1]+...+dp[n]。动态规划就出来了。

class Solution {
public:
    int countSubstrings(string s) {
        vector<int> dp(s.size(), 0);
        dp[s.size() - 1] = 1;
        for(int i = s.size() - 2; i >= 0; --i)
        {
            dp[i] = dp[i + 1] + palincount(s.substr(i, s.size() - i));
        }
        return dp[0];
    }
    int palincount(string s)   //计算以s[0]开头的回文子串有几个,遍历一遍即可
    {
        int count = 0;
        for(int i = 1; i <= s.size(); ++i)
        {
            if(ispalin(s.substr(0, i)))
            {
                count++;
            }
        }
        return count;
    }
    bool ispalin(string s)  //判断一个字符串是不是回文
    {
        int start = 0, end = s.size() - 1;
        while(start < end)
        {
            if(s[start] != s[end])
                return false;
            start ++;  //这里千万不能忘!
            end--;   //这里千万不能忘!
        }
        return true;
    }
};
但是这个题考察的绝对不是这样。这个题的思路是不局限于一维dp,而是用二维dp:
class Solution {
public:
    int countSubstrings(string s) {
        int n = s.size(), count = 0;
        vector<vector<int>> dp(n, vector<int> (n));
        for ( int end = 0; end < n; ++end ) {
            dp[end][end] = 1;
            ++count;
            for ( int start = 0; start < end; ++start ) {
                if ( s[start] == s[end] && (start+1 >= end-1 || dp[start+1][end-1])) {
                    dp[start][end] = 1;
                    ++count;
                }
            }
        }
        return count;
    }
};
定义d[i][j]:若从i到j的字符串为回文,则为真(1),否则为假(0),那么d[i][j]为真的前提是:头尾两个字符串相同并且去掉头尾以后的字串也是回文(即dp[start+1][end-1]为真),这里面要注意特殊情况,即:去掉头尾以后为空串,也是回文,比如"aa"

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值