Longest Palindromic Substring
Given a string s, the task is to find the longest substring which is a palindrome. If there are multiple answers, then return the first appearing substring.
Examples:
Input: s = "forgeeksskeegfor"
Output: "geeksskeeg"
Explanation: There are several possible palindromic substrings like "kssk", "ss", "eeksskee" etc. But the substring "geeksskeeg" is the longest among all.Input: s = "Geeks"
Output: "ee"Input: s = "abc"
Output: "a"
Input: s = ""
Output: ""
Table of Content
[Naive Approach] Generating all sub-strings - O(n^3) time and O(1) space
The idea is to generate all substrings.
- For each substring, check if it is palindrome or not.
- If substring is Palindrome, then update the result on the basis of longest palindromic substring found till now.
#include <bits/stdc++.h>
using namespace std;
// Function to check if a substring
// s[low..high] is a palindrome
bool checkPal(string &s, int low, int high) {
while (low < high) {
if (s[low] != s[high])
return false;
low++;
high--;
}
return true;
}
// function to find the longest palindrome substring
string longestPalindrome(string& s) {
// Get length of input string
int n = s.size();
// All substrings of length 1 are palindromes
int maxLen = 1, start = 0;
// Nested loop to mark start and end index
for (int i = 0; i < n; i++) {
for (int j = i; j < n; j++) {
// Check if the current substring is
// a palindrome
if (checkPal(s, i, j) && (j - i + 1) > maxLen) {
start = i;
maxLen = j - i + 1;
}
}
}
return s.substr(start, maxLen);
}
int main() {
string s = "forgeeksskeegfor";
cout << longestPalindrome(s) << endl;
return 0;
}
// Java program to find the longest
// palindromic substring.
import java.util.*;
class GfG {
// Function to check if a substring
// s[low..high] is a palindrome
static boolean checkPal(String s, int low, int high) {
while (low < high) {
if (s.charAt(low) != s.charAt(high))
return false;
low++;
high--;
}
return true;
}
// Function to find the longest palindrome substring
static String longestPalindrome(String s) {
// Get length of input string
int n = s.length();
// All substrings of length 1 are palindromes
int maxLen = 1, start = 0;
// Nested loop to mark start and end index
for (int i = 0; i < n; i++) {
for (int j = i; j < n; j++) {
// Check if the current substring is
// a palindrome
if (checkPal(s, i, j) && (j - i + 1) > maxLen) {
start = i;
maxLen = j - i + 1;
}
}
}
return s.substring(start, start + maxLen);
}
public static void main(String[] args) {
String s = "forgeeksskeegfor";
System.out.println(longestPalindrome(s));
}
}
# Python program to find the longest
# palindromic substring.
# Function to check if a substring
# s[low..high] is a palindrome
def checkPal(str, low, high):
while low < high:
if str[low] != str[high]:
return False
low += 1
high -= 1
return True
# Function to find the longest palindrome substring
def longestPalindrome(s):
# Get length of input string
n = len(s)
# All substrings of length 1 are palindromes
maxLen = 1
start = 0
# Nested loop to mark start and end index
for i in range(n):
for j in range(i, n):
# Check if the current substring is
# a palindrome
if checkPal(s, i, j) and (j - i + 1) > maxLen:
start = i
maxLen = j - i + 1
return s[start:start + maxLen]
if __name__ == "__main__":
s = "forgeeksskeegfor"
print(longestPalindrome(s))
// C# program to find the longest
// palindromic substring.
using System;
class GfG {
// Function to check if a substring
// s[low..high] is a palindrome
static bool checkPal(string s, int low, int high) {
while (low < high) {
if (s[low] != s[high])
return false;
low++;
high--;
}
return true;
}
// Function to find the longest palindrome substring
static string longestPalindrome(string s) {
// Get length of input string
int n = s.Length;
// All substrings of length 1 are palindromes
int maxLen = 1, start = 0;
// Nested loop to mark start and end index
for (int i = 0; i < n; i++) {
for (int j = i; j < n; j++) {
// Check if the current substring is
// a palindrome
if (checkPal(s, i, j) && (j - i + 1) > maxLen) {
start = i;
maxLen = j - i + 1;
}
}
}
return s.Substring(start, maxLen);
}
static void Main(string[] args) {
string s = "forgeeksskeegfor";
Console.WriteLine(longestPalindrome(s));
}
}
// JavaScript program to find the longest
// palindromic substring.
// Function to check if a substring
// s[low..high] is a palindrome
function checkPal(s, low, high) {
while (low < high) {
if (s[low] !== s[high])
return false;
low++;
high--;
}
return true;
}
// Function to find the longest palindrome substring
function longestPalindrome(s) {
// Get length of input string
const n = s.length;
// All substrings of length 1 are palindromes
let maxLen = 1, start = 0;
// Nested loop to mark start and end index
for (let i = 0; i < n; i++) {
for (let j = i; j < n; j++) {
// Check if the current substring is
// a palindrome
if (checkPal(s, i, j) && (j - i + 1) > maxLen) {
start = i;
maxLen = j - i + 1;
}
}
}
return s.substring(start, start + maxLen);
}
// Driver Code
const s = "forgeeksskeegfor";
console.log(longestPalindrome(s));
Output
geeksskeeg
[Better Approach - 1] Using Dynamic Programming - O(n^2) time and O(n^2) space
The idea is to use Dynamic Programming to store the status of smaller substrings and use these results to check if a longer substring forms a palindrome.
- The main idea behind the approach is that if we know the status (i.e., palindrome or not) of the substring ranging [i, j], we can find the status of the substring ranging [i-1, j+1] by only matching the character str[i-1] and str[j+1].
- If the substring from i to j is not a palindrome, then the substring from i-1 to j+1 will also not be a palindrome. Otherwise, it will be a palindrome only if str[i-1] and str[j+1] are the same.
- Base on this fact, we can create a 2D table (say table[][] which stores status of substring str[i . . . j] ), and check for substrings with length from 1 to N. For each length find all the substrings starting from each character i and find if it is a palindrom or not using the above idea. The longest length for which a palindrome formed will be the required asnwer.
Note: Refer to Longest Palindromic Substring using Dynamic Programming for detailed approach and code.
[Better Approach - 2] Using Expansion from center - O(n^2) time and O(1) space
The idea is to traverse each character in the string and treat it as a potential center of a palindrome, trying to expand around it in both directions while checking if the expanded substring remains a palindrome.
- For each position, we check for both odd-length palindromes (where the current character is the center) and even-length palindromes (where the current character and the next character together form the center).
- As we expand outward from each center, we keep track of the start position and length of the longest palindrome found so far, updating these values whenever we find a longer valid palindrome.
Step-by-step approach:
- Use two pointers, low and hi, for the left and right end of the current palindromic substring being found.
- Then checks if the characters at s[low] and s[hi] are the same.
- If they are, it expands the substring to the left and right by decrementing low and incrementing hi.
- It continues this process until the characters at s[low] and s[hi] are unequal or until the indices are in bounds.
- If the length of the current palindromic substring becomes greater than the maximum length, it updates the maximum length.
// C++ program to find the longest
// palindromic substring.
#include <bits/stdc++.h>
using namespace std;
// Function to find the longest palindrome substring
string longestPalindrome(string &s) {
int n = s.length();
if (n == 0) return "";
int start = 0, maxLen = 1;
// Traverse the input string
for (int i = 0; i < n; i++) {
// THIS RUNS TWO TIMES
// for both odd and even length
// palindromes. j = 0 means odd
// and j = 1 means even length
for (int j = 0; j <= 1; j++) {
int low = i;
int high = i + j;
// Expand substring while it is a palindrome
// and in bounds
while (low >= 0 && high < n && s[low] == s[high]) {
int currLen = high - low + 1;
if (currLen > maxLen) {
start = low;
maxLen = currLen;
}
low--;
high++;
}
}
}
return s.substr(start, maxLen);
}
int main() {
string s = "forgeeksskeegfor";
cout << longestPalindrome(s) << endl;
return 0;
}
// Java program to find the longest
// palindromic substring.
class GfG {
// Function to find the longest palindrome substring
static String longestPalindrome(String s) {
int n = s.length();
if (n == 0) return "";
int start = 0, maxLen = 1;
// Traverse the input string
for (int i = 0; i < n; i++) {
// THIS RUNS TWO TIMES
// for both odd and even length
// palindromes. j = 0 means odd
// and j = 1 means even length
for (int j = 0; j <= 1; j++) {
int low = i;
int high = i + j;
// Expand substring while it is a palindrome
// and in bounds
while (low >= 0 && high < n && s.charAt(low) == s.charAt(high)) {
int currLen = high - low + 1;
if (currLen > maxLen) {
start = low;
maxLen = currLen;
}
low--;
high++;
}
}
}
return s.substring(start, start + maxLen);
}
public static void main(String[] args) {
String s = "forgeeksskeegfor";
System.out.println(longestPalindrome(s));
}
}
# Python program to find the longest
# palindromic substring.
# Function to find the
# longest palindrome substring
def longestPalindrome(s):
n = len(s)
if n == 0:
return ""
start, maxLen = 0, 1
# Traverse the input string
for i in range(n):
# THIS RUNS TWO TIMES
# for both odd and even length
# palindromes. j = 0 means odd
# and j = 1 means even length
for j in range(2):
low, high = i, i + j
# Expand substring while it is a palindrome
# and in bounds
while low >= 0 and high < n and s[low] == s[high]:
currLen = high - low + 1
if currLen > maxLen:
start = low
maxLen = currLen
low -= 1
high += 1
return s[start:start + maxLen]
if __name__ == "__main__":
s = "forgeeksskeegfor"
print(longestPalindrome(s))
// C# program to find the longest
// palindromic substring.
using System;
class GfG {
// Function to find the longest palindrome substring
static string longestPalindrome(string s) {
int n = s.Length;
if (n == 0) return "";
int start = 0, maxLen = 1;
// Traverse the input string
for (int i = 0; i < n; i++) {
// THIS RUNS TWO TIMES
// for both odd and even length
// palindromes. j = 0 means odd
// and j = 1 means even length
for (int j = 0; j <= 1; j++) {
int low = i;
int high = i + j;
// Expand substring while it is a palindrome
// and in bounds
while (low >= 0 && high < n && s[low] == s[high]) {
int currLen = high - low + 1;
if (currLen > maxLen) {
start = low;
maxLen = currLen;
}
low--;
high++;
}
}
}
return s.Substring(start, maxLen);
}
static void Main(string[] args) {
string s = "forgeeksskeegfor";
Console.WriteLine(longestPalindrome(s));
}
}
// JavaScript program to find the longest
// palindromic substring.
// Function to find the longest palindrome substring
function longestPalindrome(s) {
const n = s.length;
if (n === 0) return "";
let start = 0, maxLen = 1;
// Traverse the input string
for (let i = 0; i < n; i++) {
// THIS RUNS TWO TIMES
// for both odd and even length
// palindromes. j = 0 means odd
// and j = 1 means even length
for (let j = 0; j <= 1; j++) {
let low = i;
let high = i + j;
// Expand substring while it is a palindrome
// and in bounds
while (low >= 0 && high < n && s[low] === s[high]) {
const currLen = high - low + 1;
if (currLen > maxLen) {
start = low;
maxLen = currLen;
}
low--;
high++;
}
}
}
return s.substring(start, start + maxLen);
}
// Driver Code
const s = "forgeeksskeegfor";
console.log(longestPalindrome(s));
Output
geeksskeeg
[Expected Approach] Using Manacher’s Algorithm - O(n) time and O(n) space
We can solve this problem in linear time using Manacher’s Algorithm. Refer the below links for details: