Given a string s
, return the longest palindromic substring in s
.
Example 1:
Input: s = "babad" Output: "bab" Note: "aba" is also a valid answer.
Example 2:
Input: s = "cbbd" Output: "bb"
Example 3:
Input: s = "a" Output: "a"
Example 4:
Input: s = "ac" Output: "a"
Constraints:
1 <= s.length <= 1000
s
consist of only digits and English letters.
Companies:
Amazon, Microsoft, Adobe, Apple, Wayfair, Facebook, Goldman Sachs, Oracle, Yahoo, Google, Docusign, eBay, Uber, Walmart Labs, Salesforce, Zoho, HBO, Tesla
Related Topics:
String, Dynamic Programming
Similar Questions:
- Shortest Palindrome (Hard)
- Palindrome Permutation (Easy)
- Palindrome Pairs (Hard)
- Longest Palindromic Subsequence (Medium)
- Palindromic Substrings (Medium)
Let dp[i][j]
be true
if s[i..j]
is a palindrome. The answer is the substring of the longest length that has dp[i][j] = true
.
dp[i][j] = true
dp[i][j] = s[i] == s[j] && (i+1 > j-1 || dp[i+1][j-1])
// OJ: https://leetcode.com/problems/longest-palindromic-substring/
// Author: github.com/lzl124631x
// Time: O(N^2)
// Space: O(N^2)
class Solution {
public:
string longestPalindrome(string s) {
int N = s.size(), start = 0, len = 0;
bool dp[1001][1001] = {};
for (int i = N - 1; i >= 0; --i) {
for (int j = i; j < N; ++j) {
if (i == j) dp[i][j] = true;
else dp[i][j] = s[i] == s[j] && (i + 1 > j - 1 || dp[i + 1][j - 1]);
if (dp[i][j] && j - i + 1 > len) {
start = i;
len = j - i + 1;
}
}
}
return s.substr(start, len);
}
};
Since dp[i][j]
only depends on dp[i + 1][j - 1]
, we can reduce the space complexity from O(N^2)
to O(N)
.
// OJ: https://leetcode.com/problems/longest-palindromic-substring/
// Author: github.com/lzl124631x
// Time: O(N^2)
// Space: O(N)
class Solution {
public:
string longestPalindrome(string s) {
int N = s.size(), start = 0, len = 0;
bool dp[1001] = {};
for (int i = N - 1; i >= 0; --i) {
for (int j = N - 1; j >= i; --j) {
if (i == j) dp[j] = true;
else dp[j] = s[i] == s[j] && (i + 1 > j - 1 || dp[j - 1]);
if (dp[j] && j - i + 1 > len) {
start = i;
len = j - i + 1;
}
}
}
return s.substr(start, len);
}
};
// OJ: https://leetcode.com/problems/longest-palindromic-substring/
// Author: github.com/lzl124631x
// Time: O(N^2)
// Space: O(1)
class Solution {
int expand(string &s, int L, int R) {
while (L >= 0 && R < s.size() && s[L] == s[R]) --L, ++R;
return R - L - 1;
}
public:
string longestPalindrome(string s) {
int start = 0, maxLen = 0;
for (int i = 0; i < s.size(); ++i) {
int len1 = expand(s, i, i), len2 = expand(s, i, i + 1);
int len = max(len1, len2);
if (len > maxLen) {
maxLen = len;
start = i - (len - 1) / 2;
}
}
return s.substr(start, maxLen);
}
};
// OJ: https://leetcode.com/problems/longest-palindromic-substring/
// Author: github.com/lzl124631x
// Time: O(N)
// Space: O(N)
class Solution {
public:
string longestPalindrome(string s) {
int N = s.size();
string t = "^*";
for (char c : s) {
t += c;
t += '*';
}
t += '$'; // inflating the `s` ( example: "abc" becomes "^*a*b*c*$" )
int M = t.size();
vector<int> r(M); // `r[i]` is the number of palindromes with `t[i]` as the center (aka. the radius of the longest palindrome centered at `t[i]`)
r[1] = 1;
int j = 1; // `j` is the index with the furthest reach `j + r[j]`
for (int i = 2; i <= 2 * N; ++i) {
int cur = j + r[j] > i ? min(r[2 * j - i], j + r[j] - i) : 1; // `t[2*j-i]` is the symmetry point to `t[i]`
while (t[i - cur] == t[i + cur]) ++cur; // expanding the current radius
if (i + cur > j + r[j]) j = i;
r[i] = cur;
}
int len = 1, start = 0;
for (int i = 2; i <= 2 * N; ++i) {
if (r[i] - 1 > len) {
len = r[i] - 1;
start = (i - r[i]) / 2;
}
}
return s.substr(start, len);
}
};