代码随想录算法训练营第57天|647. 回文子串,516.最长回文子序列
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |
647. 回文子串
力扣题目链接
思路
动态规划
- dp[i][j] 表示[i,j]的子字符串是否为回文字符串
- 递推公式:
- s[i]!=s[j] dp[i][j]=false;
- s[i]==s[j] if(j-i<=1) dp[i][j]=true; else if(dp[i+1][j-1]) dp[i][j]=true;
- 初始化:都初始化为fals
- 遍历顺序:从下往上从左往右
双指针法
- 枚举每一个可能的回文中心然后用两个指针分别向左右两边拓展当两个指针指向的元素相同的时候就拓展否则停止拓展。
- 一个元素可以作为中心点两个元素也可以作为中心点
代码
动态规划
class Solution {
public:
/*
* dp[i][j] 表示[i,j]的子字符串是否为回文字符串
* 递推公式:
* s[i]!=s[j] dp[i][j]=false;
* s[i]==s[j] if(j-i<=1) dp[i][j]=true; else if(dp[i+1][j-1]) dp[i][j]=true;
* 初始化:都初始化为false
* 遍历顺序:从下往上从左往右
*/
int countSubstrings(string s) {
vector<vector<bool>> dp(s.size(),vector<bool>(s.size(),false));
int result=0;
for(int i=s.size()-1;i>=0;i--){
for(int j=i;j<s.size();j++){
if(s[i]==s[j]){
if(j-i<=1){
dp[i][j]=true;
result++;
}
else if(dp[i+1][j-1]){
dp[i][j]=true;
result++;
}
}
}
}
return result;
}
};
我的解法
class Solution {
public:
/*
* dp[i][j] 表示[j,i]的子字符串是否为回文字符串
* 递推公式:
* 初始化:for(int i=0;i<s.size();i++) dp[i][j]=true;
* 遍历顺序:从左往右
*/
int countSubstrings(string s) {
vector<vector<bool>> dp(s.size(),vector<bool>(s.size(),false));
for(int i=0;i<s.size();i++){
dp[i][i]=true;
}
for(int i=1;i<s.size();i++){
for(int j=0;j<i;j++){
if(s[i]==s[j]){
if(j+1==i) dp[i][j]=true;
else dp[i][j]=dp[i-1][j+1];
}
else dp[i][j]=false;
}
}
int result=0;
for(int i=0;i<s.size();i++){
for(int j=0;j<s.size();j++){
if(dp[i][j]) result++;
}
}
return result;
}
};
双指针法
class Solution {
public:
int extend(const string& s, int i, int j, int n){
int res=0;
while(i>=0&&j<n&&s[i]==s[j]){
res++;
i--;
j++;
}
return res;
}
int countSubstrings(string s) {
int result=0;
for(int i=0;i<s.size();i++){
result+=extend(s,i,i,s.size()); // 以一个元素为中心点
result+=extend(s,i,i+1,s.size()); // 以两个元素为中心点
}
return result;
}
};
516.最长回文子序列
力扣题目链接
思路
- dp[i][j] 表示在[i,j]中最长回文子序列的长度
- 递推公式:if(s[i]==s[j]) dp[i][j]=dp[i+1][j-1]+2;
- else dp[i][j]=max(dp[i+1][j],dp[i][j-1]);
- 初始化:对角线都为1
- 遍历顺序:从下往上从左往右
代码
class Solution {
public:
/*
* dp[i][j] 表示在[i,j]中最长回文子序列的长度
* 递推公式:if(s[i]==s[j]) dp[i][j]=dp[i+1][j-1]+2;
* else dp[i][j]=max(dp[i+1][j],dp[i][j-1]);
* 初始化:对角线都为1
* 遍历顺序:从下往上从左往右
*/
int longestPalindromeSubseq(string s) {
vector<vector<int>> dp(s.size(),vector<int>(s.size(),0));
for(int i=0;i<s.size();i++) dp[i][i]=1;
for(int i=s.size()-1;i>=0;i--){
for(int j=i+1;j<s.size();j++){
if(s[i]==s[j])
dp[i][j]=dp[i+1][j-1]+2;
else
dp[i][j]=max(dp[i+1][j],dp[i][j-1]);
}
}
return dp[0][s.size()-1];
}
};