Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.
Example 1:
Input: "babad"
Output: "bab"
Note: "aba" is also a valid answer.
Example 2:
Input: "cbbd"
Output: "bb"
解法1:DP
dp[i][j] = 1,示i到j是回文子串。
即两个相连的是回文子串;
dp[i+1][j-1]是小范围的回文子串的话,左右扩充且左右扩充的想等的也是回文子串;
#include<string>
#include<vector>
#include<iostream>
using namespace std;
class max_string
{
public:
string longestPalindrome(string s) {
vector<vector<int>> array(s.length(), vector<int>(s.length()));
/*for (int i = 0; i < s.length; ++i) {
array[i].resize(s.length);
}*/
int max = 1;
int left = 0;
for (int i = 0; i < s.length(); ++i) {
array[i][i] = 1;
for (int j = 0; j < i; ++j) {
if (i - j == 1&&s[i]==s[j])
array[j][i] = 1;
if (i - j > 1 && array[j + 1][i - 1]==1 && s[i] == s[j])
array[j][i] = 1;
if (array[j][i] == 1 && i - j + 1> max) {
max = i-j+1;
left = j;
}
}
}
return s.substr(left, max);
}
};
解法2:Manacher Algorithm (马拉车算法)
为了解决奇回文和偶回文的分别讨论,在字符串插入#解决,因为n个字符,需要插入n+1个。
然后为了解决越界在头插入$,且末尾包含\0,所以还是奇数。
比如原字符串: s =”abbaTNTabcba”
插入字符之后:sNew= “$
#a#b#b#a#T#N#T#a#b#c#b#a#
p[i]为第i个字符的回文半径。1代表仅包括自己。
解决思路:计算所有字符的回文半径,通过最多的来确定最长回文。
分两种情况计算回文半径:
第一种:i<mx
id为最大回文中心,mx为半径打到最远,i为当前下标,j为对称下标。因为id-j = i - id,所以 j = 2*id -i。
根据对称性,i的半径应该等于j的半径,当i的半径覆盖的区域没有超过mx的时候,p[i] = p[j];
如果超过了,那就暴力计算吧。
第二种:i>=mx
暴力计算。
#pragma once
#include<string>
#include<vector>
using namespace std;
class malache_maxstring
{
public:
string longestPalindrome(string s) {
string s_new = "$#";
string s_out;
for (auto i = 0; i < s.length(); ++i) {
s_new += s[i];
s_new += '#';
}
int max_len = 0;
int id = 0;
int mx = 0;
vector<int> p(s_new.length(), 0);
for (int i = 1; i < s_new.length(); ++i) {
if (i < mx) {
if (mx - i >= p[2 * id - i])
p[i] = p[2 * id - i];
if (mx - i < p[2 * id - i]) {
for (int j = 1; i + j <= s_new.length(); ++j) {
if (i + j == s_new.length()) {
p[i] = j;
if (j >= max_len) {
id = i;
max_len = j;
mx = i + j - 1;
s_out = s.substr((id - max_len) / 2, max_len - 1);
}
}
else {
if (s_new[i + j] == s_new[i - j])
continue;
else {
p[i] = j;
if (j >= max_len) {
id = i;
max_len = j;
mx = i + j - 1;
s_out = s.substr((id - max_len) / 2, max_len - 1);
}
break;
}
}
}
}
}
else {
for (int j = 1; i + j <= s_new.length(); ++j) {
if (i + j == s_new.length()) {
p[i] = j;
if (j >= max_len) {
id = i;
max_len = j;
mx = i + j - 1;
s_out = s.substr((id - max_len) / 2, max_len - 1);
}
}
else {
if (s_new[i + j] == s_new[i - j])
continue;
else {
p[i] = j;
if (j >= max_len) {
id = i;
max_len = j;
mx = i + j - 1;
s_out = s.substr((id - max_len) / 2, max_len - 1);
}
break;
}
}
}
}
}
return s_out;
}
};