LeedCode_最长回文子串
题目说明
给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。
输入: “babad”
输出: “bab”
注意: “aba” 也是一个有效答案。
链接:https://leetcode-cn.com/problems/longest-palindromic-substring/
方法一:中心扩展法(时间复杂度O(n2))
int expandAroundCenter(string s, int left, int right)
{
int n = s.size();
while (left>=0&&right<n&&s[left]==s[right])
{
left--;
right++;
}
return right - left - 1;
}
string longestPalindrome1(string s)
{
int n = s.size();
if (n < 2)
{
return s;
}
int start = 0;
int end = 0;
for (int i = 0; i < n; i++)
{
int len1 = expandAroundCenter(s, i, i); //以单个字符进行扩展
int len2 = expandAroundCenter(s, i, i + 1); //以双字符进行扩展
int len = max(len1, len2);
if (len > end - start)
{
start = i - (len - 1) / 2;
end = i + len / 2;
}
}
return s.substr(start, end + 1);
}
方法二:动态规划(时间复杂度O(n2))
借助辅助状态数组dp[i]j,仅刷新上三角状态数组即可,从右下角向上刷新
string longestPalindrome2(string s)
{
int n = s.size();
if (n < 2)
{
return s;
}
vector<vector<bool>> dp(n, vector<bool>(n));
int left = 0;
int right = 0;
int len = 0;
for (int i = n-1; i >=0 ; i--)
{
int t;
for (int j = i; j < n; j++)
{
if (i == j)
{
dp[i][j] = true;
}
else if (j == i + 1)
{
dp[i][j] = s[i] == s[j];
}
else
{
dp[i][j] = dp[i + 1][j - 1]&& s[i] == s[j] ;
}
if (dp[i][j] && len < (j - i+1))
{
len = j - i + 1;
left = i;
right = j;
}
}
}
return s.substr(left,len); //此函数的含义:其起始位置,截取长度
}
方法三:马拉车(Manacher)算法
参考文章:https://blog.csdn.net/Form_/article/details/79766986
string longestPalindrome3(string s)
{
vector<char> sb;
int n = s.size();
if (n <= 1)
{
return s;
}
sb.push_back('$');
sb.push_back('#');
for (int i = 0; i < n; i++)
{
sb.push_back(s[i]);
sb.push_back('#');
}
n = sb.size();
int max_len =0;
int max_center = 0;
int id = 0;
int mx = 0;
vector<int> p(n, 0);
for (int i = 1; i < n; i++)
{
if (mx > i)
{
p[i] = min(p[2 * id - i], mx - i);
}
else
{
p[i] = 1;
}
while (i+p[i]<n&&i-p[i]>=0&&sb[i-p[i]]==sb[i+p[i]])
{
p[i]++;
}
if (mx < p[i] + i)
{
mx = i + p[i];
id = i;
}
if (max_len < p[i])
{
max_len = p[i];
max_center = i;
}
}
return s.substr((max_center - max_len) / 2, max_len-1);
}