题目描述
给你一个字符串 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;
}
};