动态规划——回文串问题
目录
1. 回文子串
2. 最长回文子串
3. 回文串分割
4. 分割回文串II
5. 最长回文子序列
6. 让字符串成为回文串的最小插入次数
1. 回文子串
题目链接:647. 回文子串 - 力扣(LeetCode)
题目展示:
题目分析:
代码实现:
class Solution {
public:
int countSubstrings(string s)
{
int n=s.size();
vector<vector<bool>> dp(n,vector<bool>(n));
int ret=0;
for(int i=n-1;i>=0;i--)
{
for(int j=i;j<n;j++)
{
if(s[i]==s[j]) dp[i][j]=i+1<j?dp[i+1][j-1]:true;
if(dp[i][j]) ret++;
}
}
return ret;
}
};
2. 最长回文子串
题目链接:5. 最长回文子串 - 力扣(LeetCode)
题目展示:
题目分析:
代码实现:
class Solution {
public:
string longestPalindrome(string s)
{
int n=s.size();
vector<vector<bool>> dp(n,vector<bool>(n));
int len=1,begin=0;
for(int i=n-1;i>=0;i--)
{
for(int j=i;j<n;j++)
{
if(s[i]==s[j]) dp[i][j]=i+1<j?dp[i+1][j-1]:true;
if(dp[i][j]&&j-i+1>len) len=j-i+1,begin=i;
}
}
return s.substr(begin,len);
}
};
3. 回文串分割
题目链接:1745. 分割回文串 IV - 力扣(LeetCode)
题目展示:
题目分析:
这道题看起来比较困难,实际上并不难,我们利用前面动态规划的思想可以瞬间降这道题变得简单。
代码实现:
class Solution {
public:
bool checkPartitioning(string s)
{
int n=s.size();
vector<vector<bool>> dp(n,vector<bool>(n));
for(int i=n-1;i>=0;i--)
{
for(int j=i;j<n;j++)
{
if(s[i]==s[j])
{
dp[i][j]=i+1<j?dp[i+1][j-1]:true;
}
}
}
for(int i=1;i<n-1;i++)
{
for(int j=i;j<n-1;j++)
{
if(dp[0][i-1]&&dp[i][j]&&dp[j+1][n-1]) return true;
}
}
return false;
}
};
4. 分割回文串II
题目链接:132. 分割回文串 II - 力扣(LeetCode)
题目展示:
题目分析:
代码实现:
class Solution {
public:
int minCut(string s)
{
int n=s.size();
vector<vector<bool>> isPal(n,vector<bool>(n));
for(int i=n-1;i>=0;i--)
{
for(int j=i;j<n;j++)
{
if(s[i]==s[j])
{
isPal[i][j]=i+1<j?isPal[i+1][j-1]:true;
}
}
}
vector<int> dp(n,INT_MAX);
for(int i=0;i<n;i++)
{
if(isPal[0][i]) dp[i]=0;
else
{
for(int j=1;j<=i;j++)
{
if(isPal[j][i]) dp[i]=min(dp[i],dp[j-1]+1);
}
}
}
return dp[n-1];
}
};
5. 最长回文子序列
题目链接:516. 最长回文子序列 - 力扣(LeetCode)
题目展示:
题目分析:
说明:填表顺序那里笔误,应该是从下往上填每一行。
代码实现:
class Solution
{
public:
int longestPalindromeSubseq(string s)
{
int n=s.size();
//创建dp表
vector<vector<int>> dp(n,vector<int>(n));
//本题无需初始化
//填表
for(int i=n-1;i>=0;i--)
{
dp[i][i]=1;
for(int j=i+1;j<n;j++)
{
if(s[i]==s[j]) dp[i][j]=dp[i+1][j-1]+2;
else dp[i][j]=max(dp[i][j-1],dp[i+1][j]);
}
}
//返回值
return dp[0][n-1];
}
};
6. 让字符串成为回文串的最小插入次数
题目链接:1312. 让字符串成为回文串的最少插入次数 - 力扣(LeetCode)
题目展示:
题目分析:
代码实现:
class Solution {
public:
int minInsertions(string s)
{
int n=s.size();
vector<vector<int>> dp(n,vector<int>(n));
for(int i=n-1;i>=0;i--)
{
dp[i][i]=0;
for(int j=i+1;j<n;j++)
{
if(s[i]==s[j]) dp[i][j]=dp[i+1][j-1];
else dp[i][j]=min(dp[i][j-1]+1,dp[i+1][j]+1);
}
}
return dp[0][n-1];
}
};