今天写了最长回文子串和最长回文子序列,有必要来记录一下这一类问题.
我觉得这类问题和最长公共子串和最长公共子序列有些相似,当然都是用dp的思想.
但是,*肯定不能通过用逆转串来转化为最长公共子串和最长公共子序列 *来解决问题.
Leetcode516 最长回文子序列(已经注释非常清晰)
class Solution {
public:
int longestPalindromeSubseq(string s) {
int dp[s.size()][s.size()];
/*
*dp[i][j]代表 以s[i]-s[j] 的最长回文子序列长度
*s[i]==s[j]&&J-I!=1 dp[i][j]=dp[i+1][j-1]+2
*s[i]==s[j]&&J-I==1 dp[i][j]=2
*s[i]!=s[j] dp[i][j]=max(dp[i+1][j],dp[i][j-1])
*/
memset(dp,0,sizeof(dp));
for(int i=0;i<s.size();i++) dp[i][i]=1;
int len=2;
for(;len<=s.size();len++){
for(int i=0;i+len-1<s.size();i++){
int j=i+len-1;//终点
//cout<<i<<" "<<j<<endl;
if(s[i]==s[j]){
if(len==2) dp[i][j]=2;
else dp[i][j]=dp[i+1][j-1]+2;
}else dp[i][j]=max(dp[i+1][j],dp[i][j-1]);
}
}
// for(int i=0;i<s.size();i++){
// for(int j=0;j<s.size();j++) cout<<dp[i][j]<<" ";
// cout<<endl;
// }
return dp[0][s.size()-1];
}
};
Leetcode5.最长回文子串(已经注释非常清晰)
class Solution {
public:
string longestPalindrome(string s) {
int dp[s.size()][s.size()];
memset(dp,0,sizeof(dp));
/*
*dp[i][j] 代表以s[i]开始s[j]结束的子串是否为回文串
*0代表不是
*1代笔是
*/
int res=-1;
int index1=0;
int index2=0;
for(int i=0;i<s.size();i++) dp[i][i]=1;//长度为1的子串必是回文字符串
int len=2;//类似于矩阵连乘 对角线开始 然后根据len确定起点和终点
for(;len<=s.size();len++){//执行s.size()-1次(可以自己画图推)
for(int i=0;i+len-1<s.size();i++){
int j=i+len-1;//i 代表起点 j代表终点
if(s[i]!=s[j]) dp[i][j]=0;
else{
if(j-i!=1) dp[i][j]=dp[i+1][j-1];
else dp[i][j]=1;//如果j=i+1 则直接等于1
}
if(dp[i][j]==1){
if(res<len){//比较长度 记录下表
res=len;
index1=i;
index2=j;
}
}
}
}
return s.substr(index1,index2-index1+1);
}
};
Leetcode647.回文子串(该题与上题思路相同,只需要统计一下dp数组里1的个数即可)
class Solution {
public:
int countSubstrings(string s) {
int dp[s.size()][s.size()];
memset(dp,0,sizeof(dp));
/*
*dp[i][j] 代表以s[i]开始s[j]结束的子串是否为回文串
*0代表不是
*1代笔是
*/
//int index1=0;
// int index2=0;
for(int i=0;i<s.size();i++) dp[i][i]=1;//长度为1的子串必是回文字符串
int res= s.size();
int len=2;//类似于矩阵连乘 对角线开始 然后根据len确定起点和终点
for(;len<=s.size();len++){//执行s.size()-1次(可以自己画图推)
for(int i=0;i+len-1<s.size();i++){
int j=i+len-1;//i 代表起点 j代表终点
if(s[i]!=s[j]) dp[i][j]=0;
else{
if(j-i!=1) dp[i][j]=dp[i+1][j-1];
else dp[i][j]=1;//如果j=i+1 则直接等于1
}
if(dp[i][j]==1){
res++;
}
}
}
return res;
}
};
~~end.