Open In App

CSES Solution – Longest Palindrome

Prerequisite: Manacher’s Algorithm

Given a string, your task is to determine the longest palindromic substring of the string. For example, the longest palindrome in aybabtu is bab.

Example:

Input: s = aybabtu
Output: bab

Input: GeeksgfgGeeks
Output: gfg

Approach:

The idea is to use Manacher’s algorithm, which is a linear time complexity algorithm for finding the longest palindromic substring in a given string.

Lets break down the intuition into some steps:

  • We'll use two arrays, oddLength[] and evenLength[], to store the lengths of the longest odd-length and even-length palindromic substrings centered at each index of the input string.
  • Odd-Length Palindromes: First calculates the longest odd-length palindromic substring centered at each index. It uses a variable length to keep track of the current length of the palindrome. It starts from the center and expands in both directions (left and right) until it finds a mismatch or reaches the boundary of the string. The left and right variables are used to keep track of the boundaries of the current longest palindrome.
  • Even-Length Palindromes: The process is repeated for even-length palindromes. The only difference is that the initial length is set to 0 and the expansion starts from one position to the left of the center.
  • Finding the Longest Palindrome: After the lengths of all palindromic substrings are calculated, iterates over the oddLength and evenLength arrays to find the maximum length and the center of the longest palindromic substring.
  • Finally, the longest palindromic substring is extracted from the input string using the substr function and returned.

Steps-by-step approach:

Below are the implementation of the above approach:

#include <iostream>
#include <string>

using namespace std;

// Arrays to store the lengths of the longest palindromic
// substrings centered at each index
int oddLength[1000005], evenLength[1000005];

// Function to find the longest palindromic substring
string solve(string& s, int n)
{

    // Find the lengths of the longest odd-length
    // palindromic substrings centered at each index
    for (int i = 0, left = 0, right = -1; i < n; i++) {

        // Initialize the length as 1 if the current index
        // is beyond the right boundary
        int length = (i > right)
                         ? 1
                         : min(oddLength[left + right - i],
                               right - i + 1);

        // Expand around the center to find the longest
        // palindrome
        while (0 <= i - length && i + length < n
               && s[i - length] == s[i + length]) {
            length++;
        }

        // Update the length of the longest odd-length
        // palindrome centered at index i
        oddLength[i] = length--;

        // Update the boundaries of the current palindrome
        if (i + length > right) {
            left = i - length;
            right = i + length;
        }
    }

    // Find the lengths of the longest even-length
    // palindromic substrings centered at each index
    for (int i = 0, left = 0, right = -1; i < n; i++) {

        // Initialize the length as 0 if the current index
        // is beyond the right boundary
        int length
            = (i > right)
                  ? 0
                  : min(evenLength[left + right - i + 1],
                        right - i + 1);

        // Expand around the center to find the longest
        // palindrome
        while (0 <= i - length - 1 && i + length < n
               && s[i - length - 1] == s[i + length]) {
            length++;
        }

        // Update the length of the longest even-length
        // palindrome centered at index i
        evenLength[i] = length--;

        // Update the boundaries of the current palindrome
        if (i + length > right) {
            left = i - length - 1;
            right = i + length;
        }
    }

    // Find the longest palindromic substring
    int maxLength = 0, center = -1;
    for (int i = 0; i < n; i++) {

        // Update the maxLength and center if a longer
        // palindrome is found
        if (oddLength[i] * 2 - 1 > maxLength) {
            maxLength = oddLength[i] * 2 - 1;
            center = i;
        }
        if (evenLength[i] * 2 > maxLength) {
            maxLength = evenLength[i] * 2;
            center = i;
        }
    }

    // Return the longest palindromic substring
    if (maxLength % 2 == 1)
        return s.substr(center - maxLength / 2, maxLength);
    return s.substr(center - maxLength / 2, maxLength);
}

// Main function
int main()
{

    // Input string
    string s = "GeeksgfgGeeks";
    int n = s.size();

    // Call the solve function and print the result
    cout << solve(s, n);

    return 0;
}
/* code by flutterfly */
import java.util.Arrays;

public class Main {

    // Arrays to store the lengths of the longest palindromic
    // substrings centered at each index
    static int[] oddLength;
    static int[] evenLength;

    // Function to find the longest palindromic substring
    static String solve(String s, int n) {
        oddLength = new int[n];
        evenLength = new int[n];

        // Find the lengths of the longest odd-length
        // palindromic substrings centered at each index
        for (int i = 0, left = 0, right = -1; i < n; i++) {

            // Initialize the length as 1 if the current index
            // is beyond the right boundary
            int length = (i > right)
                    ? 1
                    : Math.min(oddLength[left + right - i], right - i + 1);

            // Expand around the center to find the longest
            // palindrome
            while (0 <= i - length && i + length < n && s.charAt(i - length) == s.charAt(i + length)) {
                length++;
            }

            // Update the length of the longest odd-length
            // palindrome centered at index i
            oddLength[i] = length--;

            // Update the boundaries of the current palindrome
            if (i + length > right) {
                left = i - length;
                right = i + length;
            }
        }

        // Find the lengths of the longest even-length
        // palindromic substrings centered at each index
        for (int i = 0, left = 0, right = -1; i < n; i++) {

            // Initialize the length as 0 if the current index
            // is beyond the right boundary
            int length = (i > right)
                    ? 0
                    : Math.min(evenLength[left + right - i + 1], right - i + 1);

            // Expand around the center to find the longest
            // palindrome
            while (0 <= i - length - 1 && i + length < n && s.charAt(i - length - 1) == s.charAt(i + length)) {
                length++;
            }

            // Update the length of the longest even-length
            // palindrome centered at index i
            evenLength[i] = length--;

            // Update the boundaries of the current palindrome
            if (i + length > right) {
                left = i - length - 1;
                right = i + length;
            }
        }

        // Find the longest palindromic substring
        int maxLength = 0, center = -1;
        for (int i = 0; i < n; i++) {

            // Update the maxLength and center if a longer
            // palindrome is found
            if (oddLength[i] * 2 - 1 > maxLength) {
                maxLength = oddLength[i] * 2 - 1;
                center = i;
            }
            if (evenLength[i] * 2 > maxLength) {
                maxLength = evenLength[i] * 2;
                center = i;
            }
        }

        // Return the longest palindromic substring
        if (maxLength % 2 == 1)
            return s.substring(center - maxLength / 2, center + maxLength / 2 + 1);
        return s.substring(center - maxLength / 2, center + maxLength / 2);
    }

    // Main function
    public static void main(String[] args) {

        // Input string
        String s = "GeeksgfgGeeks";
        int n = s.length();

        // Call the solve function and print the result
        System.out.println(solve(s, n));
    }
}
//code by flutterfly
using System;

class Program
{
    // Arrays to store the lengths of the longest palindromic
    // substrings centered at each index
    static int[] oddLength = new int[1000005];
    static int[] evenLength = new int[1000005];

    // Function to find the longest palindromic substring
    static string Solve(string s, int n)
    {
        // Find the lengths of the longest odd-length
        // palindromic substrings centered at each index
        for (int i = 0, left = 0, right = -1; i < n; i++)
        {
            // Initialize the length as 1 if the current index
            // is beyond the right boundary
            int length = (i > right) ? 1 : Math.Min(oddLength[left + right - i], right - i + 1);

            // Expand around the center to find the longest
            // palindrome
            while (0 <= i - length && i + length < n && s[i - length] == s[i + length])
            {
                length++;
            }

            // Update the length of the longest odd-length
            // palindrome centered at index i
            oddLength[i] = length--;

            // Update the boundaries of the current palindrome
            if (i + length > right)
            {
                left = i - length;
                right = i + length;
            }
        }

        // Find the lengths of the longest even-length
        // palindromic substrings centered at each index
        for (int i = 0, left = 0, right = -1; i < n; i++)
        {
            // Initialize the length as 0 if the current index
            // is beyond the right boundary
            int length = (i > right) ? 0 : Math.Min(evenLength[left + right - i + 1], right - i + 1);

            // Expand around the center to find the longest
            // palindrome
            while (0 <= i - length - 1 && i + length < n && s[i - length - 1] == s[i + length])
            {
                length++;
            }

            // Update the length of the longest even-length
            // palindrome centered at index i
            evenLength[i] = length--;

            // Update the boundaries of the current palindrome
            if (i + length > right)
            {
                left = i - length - 1;
                right = i + length;
            }
        }

        // Find the longest palindromic substring
        int maxLength = 0, center = -1;
        for (int i = 0; i < n; i++)
        {
            // Update the maxLength and center if a longer
            // palindrome is found
            if (oddLength[i] * 2 - 1 > maxLength)
            {
                maxLength = oddLength[i] * 2 - 1;
                center = i;
            }
            if (evenLength[i] * 2 > maxLength)
            {
                maxLength = evenLength[i] * 2;
                center = i;
            }
        }

        // Return the longest palindromic substring
        if (maxLength % 2 == 1)
            return s.Substring(center - maxLength / 2, maxLength);
        return s.Substring(center - maxLength / 2, maxLength);
    }

    // Main function
    static void Main(string[] args)
    {
        // Input string
        string s = "GeeksgfgGeeks";
        int n = s.Length;

        // Call the solve function and print the result
        Console.WriteLine(Solve(s, n));
    }
}
// Arrays to store the lengths of the longest palindromic
// substrings centered at each index
let oddLength = new Array(1000005).fill(0);
let evenLength = new Array(1000005).fill(0);

// Function to find the longest palindromic substring
function solve(s) {
    let n = s.length;

    // Find the lengths of the longest odd-length
    // palindromic substrings centered at each index
    for (let i = 0, left = 0, right = -1; i < n; i++) {
        // Initialize the length as 1 if the current index
        // is beyond the right boundary
        let length = (i > right) ? 1 : Math.min(oddLength[left + right - i], right - i + 1);

        // Expand around the center to find the longest
        // palindrome
        while (i - length >= 0 && i + length < n && s[i - length] === s[i + length]) {
            length++;
        }

        // Update the length of the longest odd-length
        // palindrome centered at index i
        oddLength[i] = length--;

        // Update the boundaries of the current palindrome
        if (i + length > right) {
            left = i - length;
            right = i + length;
        }
    }

    // Find the lengths of the longest even-length
    // palindromic substrings centered at each index
    for (let i = 0, left = 0, right = -1; i < n; i++) {
        // Initialize the length as 0 if the current index
        // is beyond the right boundary
        let length = (i > right) ? 0 : Math.min(evenLength[left + right - i + 1], right - i + 1);

        // Expand around the center to find the longest
        // palindrome
        while (i - length - 1 >= 0 && i + length < n && s[i - length - 1] === s[i + length]) {
            length++;
        }

        // Update the length of the longest even-length
        // palindrome centered at index i
        evenLength[i] = length--;

        // Update the boundaries of the current palindrome
        if (i + length > right) {
            left = i - length - 1;
            right = i + length;
        }
    }

    // Find the longest palindromic substring
    let maxLength = 0, center = -1;
    for (let i = 0; i < n; i++) {
        // Update the maxLength and center if a longer
        // palindrome is found
        if (oddLength[i] * 2 - 1 > maxLength) {
            maxLength = oddLength[i] * 2 - 1;
            center = i;
        }
        if (evenLength[i] * 2 > maxLength) {
            maxLength = evenLength[i] * 2;
            center = i;
        }
    }

    // Return the longest palindromic substring
    if (maxLength % 2 === 1)
        return s.substr(center - Math.floor(maxLength / 2), maxLength);
    return s.substr(center - Math.floor(maxLength / 2), maxLength);
}

// Main function
function main() {
    // Input string
    let s = "GeeksgfgGeeks";

    // Call the solve function and print the result
    console.log(solve(s));
}

// Call the main function
main();
def solve(s: str, n: int) -> str:
    # Arrays to store the lengths of the longest palindromic
    # substrings centered at each index
    odd_length = [0] * 1000005
    even_length = [0] * 1000005

    # Function to find the longest palindromic substring

    # Find the lengths of the longest odd-length
    # palindromic substrings centered at each index
    for i in range(n):
        left, right = 0, -1
        # Initialize the length as 1 if the current index
        # is beyond the right boundary
        length = 1 if i > right else min(odd_length[left + right - i], right - i + 1)
        # Expand around the center to find the longest
        # palindrome
        while 0 <= i - length and i + length < n and s[i - length] == s[i + length]:
            length += 1
        # Update the length of the longest odd-length
        # palindrome centered at index i
        odd_length[i] = length
        length -= 1
        # Update the boundaries of the current palindrome
        if i + length > right:
            left, right = i - length, i + length

    # Find the lengths of the longest even-length
    # palindromic substrings centered at each index
    for i in range(n):
        left, right = 0, -1
        # Initialize the length as 0 if the current index
        # is beyond the right boundary
        length = 0 if i > right else min(even_length[left + right - i + 1], right - i + 1)
        # Expand around the center to find the longest
        # palindrome
        while 0 <= i - length - 1 and i + length < n and s[i - length - 1] == s[i + length]:
            length += 1
        # Update the length of the longest even-length
        # palindrome centered at index i
        even_length[i] = length
        length -= 1
        # Update the boundaries of the current palindrome
        if i + length > right:
            left, right = i - length - 1, i + length

    # Find the longest palindromic substring
    max_length, center = 0, -1
    for i in range(n):
        # Update the maxLength and center if a longer
        # palindrome is found
        if odd_length[i] * 2 - 1 > max_length:
            max_length = odd_length[i] * 2 - 1
            center = i
        if even_length[i] * 2 > max_length:
            max_length = even_length[i] * 2
            center = i

    # Return the longest palindromic substring
    if max_length % 2 == 1:
        return s[center - max_length // 2:center + max_length // 2 + 1]
    return s[center - max_length // 2:center + max_length // 2 + 1]


# Input string
s = "GeeksgfgGeeks"
n = len(s)

# Call the solve function and print the result
print(solve(s, n))

Output
gfg




Time Complexity: O(n), where n is the length of given string
Auxiliary Space: O(n)

Article Tags :