The problem of finding the Longest Palindromic Substring is a classic and fundamental challenge in computer science and string manipulation. A palindrome is a sequence of characters that reads the same forwards as it does backward. In this problem, the task is to identify and extract the longest substring within a given input string that forms a palindrome.
Several common methods and algorithms exist to solve this problem, each with its own trade-offs in terms of time and space complexity. Here is a brief introduction to some of the common methods:
During coding interview, it’s generally not recommended to start with the brute force solution. Dynamic programming is a good choice for an interview because it’s a well-known technique with a reasonable time complexity O(n^2). Expand around center is also a good choice for a coding interview because it’s relatively easy to implement.
While highly efficient, Manacher’s algorithm, Suffix Tree or Palindrome Tree are typically not suitable for a coding interview unless the interviewer explicitly asks for them. They are complex to implement and may not be expected in most interview scenarios.
The idea behind this approach is to consider each character in the given string as a potential center of a palindrome and then expand outward to check if the characters on both sides form a valid palindrome.
This technique is effective for solving problems where you need to find palindromes because it takes advantage of the inherent symmetry of palindromes.
#include <cassert>
#include <iostream>
#include <string>
using namespace std;
string expandAroundCenter(string s, int left, int right) {
while (left >= 0 && right < s.length() && s[left] == s[right]) {
left--;
right++;
}
return s.substr(left + 1, right - left - 1);
}
string longestPalindrome(string s) {
if (s.empty())
return "";
string longest = "";
for (int i = 0; i < s.length(); i++) {
string oddPalindrome = expandAroundCenter(s, i, i);
string evenPalindrome = expandAroundCenter(s, i, i + 1);
if (oddPalindrome.length() > longest.length()) {
longest = oddPalindrome;
}
if (evenPalindrome.length() > longest.length()) {
longest = evenPalindrome;
}
}
return longest;
}
int main() {
assert(longestPalindrome("a") == "a");
assert(longestPalindrome("cbbd") == "bb");
cout << "All tests passed!" << endl;
return 0;
}
This algorithm has a time complexity of O(n^2) because for each character in the string, it potentially expands outward to both the left and right sides. Space complexity is O(1) as it only requires a few extra variables to keep track of the longest palindrome found so far and the current positions of the pointers as it iterates through the input string.
The dynamic programming approach for finding the longest palindromic substring involves using a table to store whether substrings are palindromes or not. This approach has a time complexity of O(n^2), where n is the length of the input string.
#include <iostream>
#include <string>
#include <vector>
#include <cassert>
using namespace std;
string longestPalindrome(string s) {
if (s.empty())
return "";
int n = s.length();
vector<vector<bool>> dp(n, vector<bool>(n, false));
int start = 0; // Start index of the longest palindromic substring
int max_length = 1; // Length of the longest palindromic substring
// All substrings of length 1 are palindromes
for (int i = 0; i < n; i++) {
dp[i][i] = true;
}
// Check for palindromes of length 2
for (int i = 0; i < n - 1; i++) {
if (s[i] == s[i + 1]) {
dp[i][i + 1] = true;
start = i;
max_length = 2;
}
}
// Check for palindromes of length 3 or more
for (int len = 3; len <= n; len++) {
for (int i = 0; i < n - len + 1; i++) {
int j = i + len - 1; // Ending index of the current substring
// Check if the current substring is a palindrome
if (s[i] == s[j] && dp[i + 1][j - 1]) {
dp[i][j] = true;
// Update the longest palindrome information if needed
if (len > max_length) {
start = i;
max_length = len;
}
}
}
}
// Extract and return the longest palindromic substring
return s.substr(start, max_length);
}
int main() {
assert(longestPalindrome("a") == "a");
assert(longestPalindrome("cbbd") == "bb");
cout << "All tests passed!" << endl;
return 0;
}