LeetCode 5 最长回文子串 and LeetCode 647. 回文子串(区间DP)

题目描述
给你一个字符串 s,找到 s 中最长的回文子串。
示例 1:
输入:s = “babad”
输出:“bab”
解释:“aba” 同样是符合题意的答案。
示例 2:
输入:s = “cbbd”
输出:“bb”
示例 3:
输入:s = “a”
输出:“a”
示例 4:
输入:s = “ac”
输出:“a”

区间DP模板使用。
基本模本如下:首先枚举区间长度,之后枚举区间的起始位置。框架如下
其中区间终点计算过程:起点定义为 i ,终点定义为 j 。[i,j] 区间长度为len,因此j-i+1=len,所以 j = i+len-1。

for (int len = 1; len <= n; len++) //区间长度
{          
    for (int i = 1; i + len - 1 <= n; i++) //枚举起点i
    { 
        int j = i + len - 1;                 //区间终点j
        //根据题目写代码//
    }
}

该题目是要求解子串的具体值而不是子串的长度,因此需要在求解动态规划是需要求解出最长的回文子串序列,需要保存字符串最大的长度就是 j - i = len ,比较时用的是 len > ans.size() 如果 dp[i][j] 为1 ,表示区间[i , j] 之间是回文串。

class Solution {
public:
    string longestPalindrome(string s) {
        string ans;
        int n = s.size();
        vector<vector<int>> dp(n,vector<int>(n));
        for(int len=1;len<=n;len++)
            for(int i=0;i+len-1<n;i++)
            {
                int j=i+len-1;
                if(len==1) dp[i][j]=1;
                else if(len==2)  dp[i][j] = (s[i] == s[j]);
                else  dp[i][j]=(s[i]==s[j])&&dp[i+1][j-1];           
                if (dp[i][j] && len > ans.size()) 
                {
                    ans = s.substr(i, len);//注意len大于的是上次保存的字符串的长度     
                }
            }
        return ans;
    }
};

647. 回文子串
给定一个字符串,你的任务是计算这个字符串中有多少个回文子串。具有不同开始位置或结束位置的子串,即使是由相同的字符组成,也会被视作不同的子串。

示例 1:
输入:“abc”
输出:3
解释:三个回文子串: “a”, “b”, “c”
示例 2:
输入:“aaa”
输出:6
解释:6个回文子串: “a”, “a”, “a”, “aa”, “aa”, “aaa”
与上一题的整体思路类似,本题目要求解的是回文串的个数,因此只需要将dp数组中为1的记录下来即可。

class Solution {
public:
    int countSubstrings(string s) {
        int n=s.size();
        int ans=0;
        vector<vector<int>> dp(n,vector<int>(n));
        for(int len=1;len<=n;len++)
        {
            for(int i=0;len+i-1<n;i++)
            {
                int j=len+i-1;
                if(len==1) dp[i][j]=1;
                else if(len==2) dp[i][j]=(s[i]==s[j]);
                else  dp[i][j]=(s[i]==s[j]) && dp[i+1][j-1];         
                if(dp[i][j])  ans++;         
            }
        }
        return ans;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值