最长回文子串
给你一个字符串 s,找到 s 中最长的回文子串。
如果字符串的反序与原始字符串相同,则该字符串称为回文字符串。
示例 1:
输入:s = "babad"
输出:"bab"
解释:"aba" 同样是符合题意的答案。
示例 2:
输入:s = "cbbd"
输出:"bb"
提示:
1 <= s.length <= 1000
s 仅由数字和英文字母组成
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/longest-palindromic-substring
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解题思路1:动态规划
见注释。
code
class Solution {
public:
//朴素写法:遍历每一个子串并判断是否为回文串
//o(n^2)遍历以及O(n)的判断时间复杂度
//一种是优化O(n ^ 2),尝试用双指针
//双指针or滑动窗口:同一端出发,遇到不是回文串就退出?显然不行
//从数组两端出发,也不行,向那边移动呢?
//一种是优化回文子串的判断
//优化回文子串的判断时间:利用已有的回文子串的信息进行辅助判断
//"aba" -> "xabax" or "xabay"
//动态规划来利用已有的信息辅助判断回文子串
//状态表示:f[i,j]子串[i,j]是否为回文串
//状态转移:f[i,j] = f[i+1,j-1] && (s[i] == s[j])
//初始化:单个字符必然是回文串 && 两个字符的也要单独判断
//遍历顺序:先初始化f[i+1,j-1],会先使用i+1的值,因此i要倒序遍历,j可以顺序遍历
string longestPalindrome(string s) {
int n = s.size();
vector<vector<int>> f(n,vector<int>(n,0));
for(int i = 0;i < n;i ++) f[i][i] = 1;
for(int i = n-1;i >= 0;i --)
{
for(int j = i + 1;j < n;j ++)
{
if(j - i == 1 && s[i] == s[j]) f[i][j] = 1;
else if(f[i+1][j-1] && (s[i] == s[j])) f[i][j] = 1;
}
}
pair<int,int> longest = {0,0};
int i,j;
for(i = 0;i < n;i ++)
{
for(j = i;j < n;j ++)
{
if(f[i][j] && j - i + 1 >= longest.second - longest.first + 1) longest = {i,j};
}
}
return s.substr(longest.first,longest.second - longest.first + 1);
}
};
解题思路2:中心扩散法
使用动态规划的空间复杂度是\(O(n^2)\)。接下来尝试对动态规划的时间复杂度进行优化。为了利用原有的回文子串的信息,我们只需要不断向外扩展两个字符串即可,就可以找到当前为中心开始向外扩展的可以到达的最长的字符串,中心可以是单个的字符串也可以是两个相同的字符串。
code
class Solution {
public:
pair<int,int> diffusion(string & s,int i,int j)
{
while(i >= 0 && j < s.size())
{
if(i - 1 >= 0 && j + 1 < s.size() && s[i-1] == s[j+1]) i --,j++;
else break;
}
return {i,j};
}
string longestPalindrome(string s) {
int n = s.size();
pair<int,int> longest;
for(int i = 0;i < n;i ++)
{
pair<int,int> find;
find = diffusion(s,i,i);
if(find.second - find.first + 1 >= longest.second - longest.first + 1) longest = find;
if(i + 1 < n && s[i] == s[i+1]) find = diffusion(s,i,i+1);
if(find.second - find.first + 1 >= longest.second - longest.first + 1) longest = find;
}
return s.substr(longest.first,longest.second - longest.first + 1);
}
};