| Difficulty | Medium | |||
|---|---|---|---|---|
| Source | 160 Days of Problem Solving | |||
| Tags |
|
The problem can be found at the following link: Question Link
Given a string s, your task is to find the longest palindromic substring within s.
- A substring is a contiguous sequence of characters within the string (i.e.,
s[i...j]for0 ≤ i ≤ j < len(s)). - A palindrome reads the same forwards and backwards, i.e.,
reverse(s) == s. - If there are multiple palindromic substrings of the same maximum length, return the first occurrence from left to right.
s = "forgeeksskeegfor"
"geeksskeeg"
Possible palindromic substrings include "kssk", "ss", "eeksskee", etc. However, "geeksskeeg" is the longest among them.
s = "Geeks"
"ee"
The substring "ee" is the longest palindrome in "Geeks".
s = "abc"
"a"
All substrings "a", "b", and "c" have length 1, which is the maximum. Returning the first occurrence results in "a".
$(1 \leq s.\text{size()} \leq 10^3)$ -
sconsists of only lowercase English letters.
- A palindrome can be expanded from its center.
- For each index
iin the string:- Consider two scenarios for the center:
- Odd-length palindromes (center at
i). - Even-length palindromes (center between
iandi+1).
- Odd-length palindromes (center at
- Consider two scenarios for the center:
- Expand outwards while left and right characters match.
- Track the maximum length palindrome found and its start position.
This approach checks each possible center in O(N) and potentially expands in O(N), leading to O(N²) overall time.
- Expected Time Complexity: O(N²), because for each index we can expand in both directions.
- Expected Auxiliary Space Complexity: O(1), since we use only a few extra variables for tracking indices and lengths.
class Solution {
public:
string longestPalindrome(string &s) {
int n = s.size(), start = 0, maxLen = 0;
for (int i = 0; i < n; i++) {
for (int l : {i, i + 1}) {
int j = i;
while (j >= 0 && l < n && s[j] == s[l]) j--, l++;
if (l - j - 1 > maxLen) start = j + 1, maxLen = l - j - 1;
}
}
return s.substr(start, maxLen);
}
};- Create a 2D DP table
dp[i][j], wheredp[i][j]istrueifs[i:j]is a palindrome. - Set
dp[i][i] = true(single-character substrings are palindromes). - If two adjacent characters are equal (
s[i] == s[i+1]), setdp[i][i+1] = true. - For substrings of length 3 or more, use the formula:
dp[i][j] = (s[i] == s[j] && dp[i+1][j-1])
- Keep track of the longest palindrome found and return it.
class Solution {
public:
string longestPalindrome(string &s) {
string t = "#";
for (char c : s) t += c, t += "#";
int n = t.size(), center = 0, right = 0, maxLen = 0, start = 0;
vector<int> p(n, 0);
for (int i = 0; i < n; i++) {
int mirror = 2 * center - i;
if (i < right) p[i] = min(right - i, p[mirror]);
while (i - p[i] - 1 >= 0 && i + p[i] + 1 < n && t[i - p[i] - 1] == t[i + p[i] + 1])
p[i]++;
if (i + p[i] > right) center = i, right = i + p[i];
if (p[i] > maxLen) maxLen = p[i], start = (i - maxLen) / 2;
}
return s.substr(start, maxLen);
}
};🔹 Easy to understand
🔹 Uses O(N²) space for the DP table
- Transform the original string by inserting special characters (
#) between characters to handle even-length palindromes.- Example:
"abc"→"#a#b#c#"
- Example:
- Use a palindrome radius array
p[i]to store the length of the longest palindrome centered ati. - Maintain a center (
C) and right boundary (R), representing the rightmost palindrome found. - If
iis withinR, mirror the value ofp[i]from the symmetric point acrossC. - Expand the palindrome at
iwhile characters match. - If the palindrome at
iexpands beyondR, updateCandR. - Extract the longest palindrome from
p[i].
class Solution {
public:
string longestPalindrome(string &s) {
if (s.empty()) return "";
string t = "#";
for (char c : s) t += c, t += "#";
int n = t.size(), C = 0, R = 0, maxLen = 0, center = 0;
vector<int> p(n, 0);
for (int i = 0; i < n; i++) {
int mirror = 2 * C - i;
if (i < R) p[i] = min(R - i, p[mirror]);
while (i + p[i] + 1 < n && i - p[i] - 1 >= 0 && t[i + p[i] + 1] == t[i - p[i] - 1])
p[i]++;
if (i + p[i] > R) C = i, R = i + p[i];
if (p[i] > maxLen) maxLen = p[i], center = i;
}
int start = (center - maxLen) / 2;
return s.substr(start, maxLen);
}
};🔹 Fastest solution (O(N))
🔹 Requires string transformation
| Approach | ⏱️ Time Complexity | 🗂️ Space Complexity | ✅ Pros | |
|---|---|---|---|---|
| Expand Around Center | 🟡 O(N²) | 🟢 O(1) | Simple and uses constant extra space | Slower for larger strings |
| Dynamic Programming | 🟡 O(N²) | 🟡 O(N²) | Straight-forward to implement | High space usage (DP table) |
| Manacher’s Algorithm | 🟢 O(N) | 🟢 O(N) | Fastest known approach | String transformation can be tricky to code |
- ✅ For best runtime performance: Use Manacher’s Algorithm (O(N)).
- ✅ For simplicity and minimal space usage: Use Expand Around Center (O(N²)).
- ✅ For detailed table-based logic understanding: Use Dynamic Programming (O(N²)).
class Solution {
static String longestPalindrome(String s) {
int n = s.length(), start = 0, maxLen = 0;
for (int i = 0; i < n; i++)
for (int l : new int[]{i, i + 1}) {
int j = i;
while (j >= 0 && l < n && s.charAt(j) == s.charAt(l)) {
j--;
l++;
}
if (l - j - 1 > maxLen) {
start = j + 1;
maxLen = l - j - 1;
}
}
return s.substring(start, start + maxLen);
}
}class Solution:
def longestPalindrome(self, s):
start, max_len = 0, 0
for i in range(len(s)):
for l in [i, i + 1]:
j = i
while j >= 0 and l < len(s) and s[j] == s[l]: j, l = j - 1, l + 1
if l - j - 1 > max_len: start, max_len = j + 1, l - j - 1
return s[start:start + max_len]For discussions, questions, or doubts related to this solution, feel free to connect on LinkedIn: Any Questions. Let’s make this learning journey more collaborative!
⭐ If you find this helpful, please give this repository a star! ⭐