目录
动态规划
动态规划思维(基础)
状态表示(最重要)
状态转移方程(最难)
初始化(细节)
填表顺序(细节)
返回值(结果)
回文子串 ⭐⭐
【题目解析】
【算法原理】
C++ 算法代码
最长回文子串 ⭐⭐
【题目解析】
【算法原理】
C++ 算法代码
回文串分割Ⅳ⭐⭐⭐
【题目解析】
【算法原理】
C++ 算法代码
动态规划一般会先定义一个dp表,dp表一般为一维数组 / 二位数组。如:一维数组,会先创建一个一维数组(dp表),接下来就是想办法将这个dp填满,而填满之后里面的某一个值就是最终结果。
#问:是什么?
#问:怎么来?
#问:是什么?
#问:有什么作用?
dp表是根据状态转移方程进行的,而状态转移方程是通过已有状态推出未知状态。
#问:有什么作用?
题目要求 + 状态表示。
⭐⭐⭐DP解回文串问题核心:能够将所有的字串是否是回文的信息,保存在dp表中。
647. 回文子串 - 力扣(LeetCode)
为了能表示出来所有的子串,我们可以创建⼀个 n * n 的⼆维 dp 表,只用到「上三角部分」即可。 其中, dp[i][j] 表示: s 字符串 [i, j] 的子串,是否是回文串。
每层逻辑。
#:状态表示:
#:状态转移方程:
#:初始化:
因为我们的状态转移方程分析的很细致,因此无需初始化。
#:填表顺序:
根据「状态转移方程」,我们需要「从下往上」填写每⼀行,每⼀行的顺序无所谓。
#:返回值:
根据「状态表示和题目要求」,我们需要返回 dp 表中 true 的个数。
class Solution {
public:
int countSubstrings(string s) {
int ret = 0;
// 1、创建dp表
vector> dp(s.size(), vector(s.size(), false));
// 2、初始化
// 3、填表
for(int i = s.size() - 1; i >= 0; i--)
{
for(int j = i; j < s.size(); 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;
}
};
5. 最长回文子串 - 力扣(LeetCode)
与上一题一样。
#:状态表示:
#:状态转移方程:
#:初始化:
因为我们的状态转移方程分析的很细致,因此无需初始化。
#:填表顺序:
根据「状态转移方程」,我们需要「从下往上」填写每⼀行,每⼀行的顺序无所谓。
#:返回值:
根据「状态表示和题目要求」,我们需要返回 dp 表中 true 的个数。
class Solution {
public:
string longestPalindrome(string s) {
int ret_max = 0;
int begin_index = 0;
// 1、创建dp表
vector> dp(s.size(), vector(s.size(), false));
// 2、初始化
// 3、填表
for(int i = s.size() - 1; i >= 0; i--)
{
for(int j = i; j < s.size(); 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 > ret_max)
{
ret_max = j - i + 1 ;
begin_index = i;
}
}
}
// 4、返回值
return s.substr(begin_index, ret_max);
}
};
1745. 回文串分割 IV - 力扣(LeetCode)
与上题和上上题一样。
因为其能够将所有的字串是否是回文的信息,保存在dp表中。所以我们只需要在前述中,最后加入一个判断。
#:状态表示:
#:状态转移方程:
#:初始化:
因为我们的状态转移方程分析的很细致,因此无需初始化。
#:填表顺序:
根据「状态转移方程」,我们需要「从下往上」填写每⼀行,每⼀行的顺序无所谓。
#:返回值:
根据「状态表示和题目要求」,我们需要返回 dp[0][i - 1] && dp[i][j] && dp[j + 1][s.size() - 1] 循环判断。
class Solution {
public:
bool checkPartitioning(string s) {
// 1、创建dp表
vector> dp(s.size(), vector(s.size(), false));
// 2、初始化
// 3、填表
for(int i = s.size() - 1; i >= 0; i--)
{
for(int j = i; j < s.size(); j++)
{
if(s[i] == s[j])
dp[i][j] = i + 1 < j ? dp[i + 1][j - 1] : true;
}
}
// 4、返回值
for(int i = 1; i < s.size() - 1; i++)
{
for(int j = i; j < s.size() - 1; j++)
{
if(dp[0][i - 1] && dp[i][j] && dp[j + 1][s.size() - 1])
return true;
}
}
return false;
}
};