647.回文子串
思路:确定dp数组及其下标含义,dp[i][j]表示以s[i]开头s[j]结尾的字符串是否为回文串。递推公式为if(s[i]==s[j]),判断j和i的位置关系 j==i或者j==i+1,dp[i][j] = true; 如果j>i+1且dp[i+1][j-1] = true,dp[i][j] = true;初始化,因为循环中能判断i=j为true的情况,所以一开始所有元素都初始化为false,遍历顺序由于dp[i][j]由左下推得,i从大到小,j从小到大。打印dp数组,可以用于debug。
class Solution {
public:
int countSubstrings(string s) {
//定义dp数组及其下标含义 dp[i][j]代表以s[i]开头s[j]结尾的子串是否是回文子串 bool
//递推公式 if(s[i]==s[j]) j>=i 分三种情况
//j=i dp[i][j] =true;
//j=i+1 dp[i][j] = true;
//j>i && dp[i+1][j-1] =true dp[i][j] = true;
int size = s.size();
vector<vector<bool>> dp(size,vector<bool> (size,false));
int count=0;
for(int i =size-1;i>=0;i--)
{
for(int j =i;j<size;j++)
{
if(s[i]==s[j])
{
if(j==i||j==i+1)
{
dp[i][j] = true;
count++;
}
else if(j>i && dp[i+1][j-1]==true)
{
dp[i][j] = true;
count++;
}
}
}
}
return count;
}
};
516.最长回文子序列
思路:确定dp数组及其下标含义,dp[i][j]表示以s[i]开头s[j]结尾的最长回文子序列长度。递推公式:if(s[i] == s[j]) dp[i][j] = dp[i+1][j-1]+2。否则 考虑放入s[i]或者s[j],dp[i][j-1], dp[i+1][j] 看他们俩谁更大,dp[i][j] = max (dp[i][j-1],dp[i+1][j]). 初始化,dp[i][i] =1.遍历顺序i从大到小,j从小到大,打印dp数组,可以用于debug。
class Solution {
public:
int longestPalindromeSubseq(string s) {
//定义dp[i][j]为以s[i]为开头s[j]为结尾的回文子序列长度
//递推公式 if(s[i]==s[j]) dp[i][j] = d[i+1][j-1]+2;
//else dp[i][j] = max(max(dp[i][j-1],dp[i+1][j]),dp[i-1][j-1])
int size = s.size();
vector<vector<int>> dp(size,vector<int>(size,0));
int result=0;
if(size==1)
{
return 1;
}
for(int i = 0;i<size;i++)
{
dp[i][i] = 1;
}
for(int i = size-1;i>=0;i--)
{
for(int j =i+1;j<size;j++)
{
if(s[i]==s[j])
{
dp[i][j] =dp[i+1][j-1]+2;
result = result>dp[i][j]?result:dp[i][j];
}
else if(s[i]!=s[j]&&i<size-1&&j>0)
{
dp[i][j] = max(dp[i+1][j],dp[i][j-1]);
result = result>dp[i][j]?result:dp[i][j];
}
}
}
return result;
}
};
收获:
判断回文子串,可以根据s[i]==s[j]时,j和i的位置关系,来判断dp[i][j]的状态。
dp[i][j]根据需要定义为以s[i]开头s[j]结尾的字符串是否为回文串/回文子序列最大长度