1、题目描述
给你一个字符串 s,找到 s 中最长的 回文 子串。
示例 1:
输入:s = "babad"
输出:"bab"
解释:"aba" 同样是符合题意的答案。
示例 2:
输入:s = "cbbd"
输出:"bb"
2、中心扩展法解题
- 解题思路:回文中心的两侧互相对称。因此,回文可以从他的中心展开,并且只有 2n-1 个这样的中心(一个元素为中心的情况有 n 个,两个元素为中心的情况有 n-1 个)
class Solution {
public:int expand(const std::string& s, int l, int r) {while(l >= 0 && r < s.length() && s[l] == s[r]) {--l;++r;}// 这里需要注意边界问题处理,代码走到这里时,l、r相比回文串的索引都移动了一位return r - l - 1;
}
std::string longestPalindrome(std::string s) {int len = s.length();int m = 0, index = 0;for (int i = 0; i < len; ++i) {int l1 = expand(s, i, i);int l2 = expand(s, i, i + 1);if(std::max(l2, l1) > m) {index = i - (std::max(l2, l1) - 1) / 2;m = std::max(l2, l1);}}return s.substr(index, m);
}
};
3、Dp解题
- 初始状态:
1)dp[i][i]=1; //单个字符是回文串
2)dp[i][i+1]=1 if s[i]=s[i+1]; //连续两个相同字符是回文串
std::string longestPalindrome_dp(std::string s) {int len = s.length();int max = 1, index = 0;std::vector<std::vector<std::uint8_t>> dp = std::vector<std::vector<std::uint8_t>>(len, std::vector<std::uint8_t>(len, 0));for (int i = 0; i < len; ++i) {dp[i][i] = 1;if(i + 1 < len && s[i] == s[i+1]) {dp[i][i+1] = 1;max = 2;index = i;}}for(int i = 3; i <= len; i++) {for(int j = i - 1; j < len; j++) {if(s[j] == s[j - i + 1] && dp[j-i+2][j-1] == 1) {max = i;index = j - i + 1;dp[j-i+1][j]=1;}}}return s.substr(index, max);}
- 总结,一直对这种斜线充填数据的DP不是很理解,通过这道题目悟出来,一般和个数有关的场景使用这种方式初始化数据。可以理解为是那种确定步长时怎么怎么样,因为这种方式有一个特点,那就是i-j的差值是固定的,也就是说dp[i][j]的含义是[i, j]之间的数据满足什么样的条件。