Open In App

Longest palindromic string formed by concatenation of prefix and suffix of a string

Given string str, the task is to find the longest palindromic substring formed by the concatenation of the prefix and suffix of the given string str.

Examples: 



Input: str = “rombobinnimor” 
Output: rominnimor 
Explanation: 
The concatenation of string “rombob”(prefix) and “mor”(suffix) is “rombobmor” which is a palindromic string. 
The concatenation of string “rom”(prefix) and “innimor”(suffix) is “rominnimor” which is a palindromic string. 
But the length of “rominnimor” is greater than “rombobmor”. 
Therefore, “rominnimor” is the required string.

Input: str = “geekinakeeg” 
Output: geekakeeg 
Explanation: 
The concatenation of string “geek”(prefix) and “akeeg”(suffix) is “geekakeeg” which is a palindromic string. 
The concatenation of string “geeki”(prefix) and “keeg”(suffix) is “geekigeek” which is a palindromic string. 
But the length of “geekakeeg” is equals to “geekikeeg”. 
Therefore, any of the above string is the required string.
 



Approach: The idea is to use KMP Algorithm to find the longest proper prefix which is a palindrome of the suffix of the given string str in O(N) time.  

Below is the implementation of the above approach:




// C++ implementation of the above approach
#include <bits/stdc++.h>
using namespace std;
 
// Function used to calculate the longest prefix
// which is also a suffix
int kmp(string s)
{
    vector<int> lps(s.size(), 0);
 
    // Traverse the string
    for (int i = 1; i < s.size(); i++) {
 
        int previous_index = lps[i - 1];
 
        while (previous_index > 0
               && s[i] != s[previous_index]) {
 
            previous_index = lps[previous_index - 1];
        }
 
        // Update the lps size
        lps[i] = previous_index
                 + (s[i] == s[previous_index] ? 1 : 0);
    }
 
    // Returns size of lps
    return lps[lps.size() - 1];
}
 
// Function to calculate the length of longest
// palindromic substring which is either a
// suffix or prefix
int remainingStringLongestPallindrome(string s)
{
    // Append a character to separate the string
    // and reverse of the string
    string t = s + "?";
 
    // Reverse the string
    reverse(s.begin(), s.end());
 
    // Append the reversed string
    t += s;
 
    return kmp(t);
}
 
// Function to find the Longest palindromic
// string formed from concatenation of prefix
// and suffix of a given string
string longestPrefixSuffixPallindrome(string s)
{
    int length = 0;
    int n = s.size();
 
    // Calculating the length for which prefix
    // is reverse of suffix
    for (int i = 0, j = n - 1; i < j; i++, j--) {
        if (s[i] != s[j]) {
            break;
        }
        length++;
    }
 
    // Append prefix to the answer
    string ans = s.substr(0, length);
  
 
    // Store the remaining string
    string remaining = s.substr(length,
                                (n - (2 * length)));
   
 
    // If the remaining string is not empty
    // that means that there can be a palindrome
    // substring which can be added between the
    // suffix & prefix
    if (remaining.size()) {
 
        // Calculate the length of longest prefix
        // palindromic substring
        int longest_prefix
            = remainingStringLongestPallindrome(remaining);
 
        // Reverse the given string to find the
        // longest palindromic suffix
        reverse(remaining.begin(), remaining.end());
       
        // Calculate the length of longest prefix
        // palindromic substring
        int longest_suffix
            = remainingStringLongestPallindrome(remaining);
 
        // If the prefix palindrome is greater
        // than the suffix palindrome
        if (longest_prefix > longest_suffix) {
 
            reverse(remaining.begin(), remaining.end());
 
            // Append the prefix to the answer
            ans += remaining.substr(0, longest_prefix);
        }
 
        // If the suffix palindrome is greater than
        // the prefix palindrome
 
        else {
 
            // Append the suffix to the answer
            ans += remaining.substr(0, longest_suffix);
        }
    }
 
    // Finally append the suffix to the answer
    ans += s.substr(n - length, length);
 
    // Return the answer string
    return ans;
}
 
// Driver Code
int main()
{
    string str = "rombobinnimor";
 
    cout << longestPrefixSuffixPallindrome(str)
         << endl;
}




/*package whatever //do not write package name here */
 
import java.io.*;
import java.lang.*;
import java.util.*;
class GFG {
    static String makeReverse(String str)
    {
        StringBuffer s = new StringBuffer(str);
        str = s.reverse().toString();
        String[] rev = str.split(" ");
        StringBuffer reverse = new StringBuffer();
        for (int i = rev.length - 1; i >= 0; i--) {
            reverse.append(rev[i]).append(" ");
        }
        return reverse.toString();
    }
    static int kmp(String s)
    {
        int[] lps = new int[s.length()];
        for (int i = 1; i < s.length(); i++) {
            int previous_index = lps[i - 1];
            while (previous_index > 0
                   && s.charAt(i)
                          != s.charAt(previous_index)) {
                previous_index = lps[previous_index - 1];
            }
            lps[i]
                = previous_index
                  + (s.charAt(i) == s.charAt(previous_index)
                         ? 1
                         : 0);
        }
        return lps[lps.length - 1];
    }
    static int remainingStringLongestPallindrome(String s)
    {
        String t = s + "?";
        String reversed
            = new StringBuilder(s).reverse().toString();
        t += reversed;
        return kmp(t);
    }
    static String longestPrefixSuffixPallindrome(String s)
    {
        int length = 0;
        int n = s.length();
        for (int i = 0, j = n - 1; i < j; i++, j--) {
            if (s.charAt(i) != s.charAt(j)) {
                break;
            }
            length++;
        }
        String ans = s.substring(0, length);
        String remaining
            = s.substring(length, (n - length));
        if (remaining.length() > 0) {
            int longest_prefix
                = remainingStringLongestPallindrome(
                    remaining);
            remaining = new StringBuilder(remaining)
                            .reverse()
                            .toString();
            int longest_suffix
                = remainingStringLongestPallindrome(
                    remaining);
            if (longest_prefix > longest_suffix) {
                ans += remaining.substring(0,
                                           longest_prefix);
            }
            else {
                ans += remaining.substring(0,
                                           longest_suffix);
            }
        }
        ans += s.substring(n - length);
        return ans;
    }
    public static void main(String[] args)
    {
        String str = "rombobinnimor";
        System.out.println(
            longestPrefixSuffixPallindrome(str));
    }
}
// This code is contributed by Shivam Tiwari




# Python3 implementation of
# the above approach
 
# Function used to calculate
# the longest prefix
# which is also a suffix
def kmp(s):
 
    lps = [0] * (len(s))
 
    # Traverse the string
    for i in range (1 , len(s)):
 
        previous_index = lps[i - 1]
 
        while (previous_index > 0 and
               s[i] != s[previous_index]):
 
            previous_index = lps[previous_index - 1]
        
        # Update the lps size
        lps[i] = previous_index
        if (s[i] == s[previous_index]):
            lps[i] += 1
 
    # Returns size of lps
    return lps[- 1]
 
# Function to calculate the length of
# longest palindromic substring which
# is either a suffix or prefix
def remainingStringLongestPallindrome(s):
 
    # Append a character to separate
    # the string and reverse of the string
    t = s + "?"
 
    # Reverse the string
    s = s[: : -1]
 
    # Append the reversed string
    t += s
 
    return kmp(t)
 
# Function to find the Longest
# palindromic string formed from
# concatenation of prefix
# and suffix of a given string
def longestPrefixSuffixPallindrome(s):
 
    length = 0
    n = len(s)
 
    # Calculating the length
    # for which prefix
    # is reverse of suffix
    i = 0
    j = n - 1
    while i < j:
        if (s[i] != s[j]):
            break
        i += 1
        j -= 1
         
        length += 1
 
    # Append prefix to the answer
    ans = s[0 : length]
 
    # Store the remaining string
    remaining = s[length :  length + (n - (2 * length))]
 
    # If the remaining string is not empty
    # that means that there can be a palindrome
    # substring which can be added between the
    # suffix & prefix
    if (len(remaining)):
 
        # Calculate the length of longest prefix
        # palindromic substring
        longest_prefix = remainingStringLongestPallindrome(remaining);
 
        # Reverse the given string to find the
        # longest palindromic suffix
        remaining = remaining[: : -1]
 
        # Calculate the length of longest prefix
        # palindromic substring
        longest_suffix = remainingStringLongestPallindrome(remaining);
 
        # If the prefix palindrome is greater
        # than the suffix palindrome
        if (longest_prefix > longest_suffix):
 
            remaining = remaining[: : -1]
 
            # Append the prefix to the answer
            ans += remaining[0 : longest_prefix]
        
        # If the suffix palindrome is
        # greater than the prefix palindrome
        else:
 
            # Append the suffix to the answer
            ans += remaining[0 : longest_suffix]
        
    # Finally append the suffix to the answer
    ans += s[n - length : n]
 
    # Return the answer string
    return ans
 
# Driver Code
if __name__ == "__main__"
    st = "rombobinnimor"
    print (longestPrefixSuffixPallindrome(st))
          
# This code is contributed by Chitranayal




<script>
 
// JavaScript implementation of
// the above approach
 
// Function used to calculate
// the longest prefix
// which is also a suffix
function kmp(s){
 
    let lps = new Array(s.length).fill(0)
 
    // Traverse the string
    for(let i = 1; i < s.length; i++){
 
        let previous_index = lps[i - 1]
 
        while (previous_index > 0 && s[i] != s[previous_index])
 
            previous_index = lps[previous_index - 1]
         
        // Update the lps size
        lps[i] = previous_index
        if (s[i] == s[previous_index])
            lps[i] += 1
    }
 
    // Returns size of lps
    return lps[lps.length-1]
 
}
 
// Function to calculate the length of
// longest palindromic substring which
// is either a suffix or prefix
function remainingStringLongestPallindrome(s){
 
    // Append a character to separate
    // the string and reverse of the string
    t = s + "?"
 
    // Reverse the string
    s = s.split("").reverse().join("")
 
    // Append the reversed string
    t += s
 
    return kmp(t)
}
 
// Function to find the Longest
// palindromic string formed from
// concatenation of prefix
// and suffix of a given string
function longestPrefixSuffixPallindrome(s){
 
    let length = 0
    let n = s.length
 
    // Calculating the length
    // for which prefix
    // is reverse of suffix
    let i = 0
    let j = n - 1
    while(i < j){
        if (s[i] != s[j])
            break
        i += 1
        j -= 1
         
        length += 1
    }
 
    // Append prefix to the answer
    let ans = s.substring(0,length)
 
    // Store the remaining string
    let remaining = s.substring(length,length + (n - (2 * length)))
 
    // If the remaining string is not empty
    // that means that there can be a palindrome
    // substring which can be added between the
    // suffix & prefix
    if(remaining.length){
 
        // Calculate the length of longest prefix
        // palindromic substring
        longest_prefix = remainingStringLongestPallindrome(remaining);
 
        // Reverse the given string to find the
        // longest palindromic suffix
        remaining = remaining.split("").reverse().join("")
 
        // Calculate the length of longest prefix
        // palindromic substring
        longest_suffix = remainingStringLongestPallindrome(remaining);
 
        // If the prefix palindrome is greater
        // than the suffix palindrome
        if (longest_prefix > longest_suffix){
 
            remaining = remaining.split("").reverse().join("")
 
            // Append the prefix to the answer
            ans += remaining.substring(0,longest_prefix)
        }
         
        // If the suffix palindrome is
        // greater than the prefix palindrome
        else
            // Append the suffix to the answer
            ans += remaining.substring(0,longest_suffix)
    }
         
    // Finally append the suffix to the answer
    ans += s.substring(n - length,n)
 
    // Return the answer string
    return ans
}
 
// Driver Code
 
let st = "rombobinnimor"
document.write(longestPrefixSuffixPallindrome(st))
         
// This code is contributed by shinjanpatra
 
</script>




using System;
using System.Collections.Generic;
using System.Linq;
// Function used to calculate the longest prefix
// which is also a suffix
namespace LongestPrefixSuffixPallindrome
{
    class Program
    {
        static int KMP(string s)
        {
            List<int> lps = new List<int>(new int[s.Length]);
 
            for (int i = 1; i < s.Length; i++)
            {
                int previousIndex = lps[i - 1];
 
                while (previousIndex > 0 && s[i] != s[previousIndex])
                {
                    previousIndex = lps[previousIndex - 1];
                }
 
                lps[i] = previousIndex + (s[i] == s[previousIndex] ? 1 : 0);
            }
 
            return lps[lps.Count - 1];
        }
        // Function to calculate the length of longest
        // palindromic substring which is either a
        // suffix or prefix
        static int RemainingStringLongestPallindrome(string s)
        {
            string t = s + "?";
 
            string reverse = new string(s.Reverse().ToArray());
            t += reverse;
 
            return KMP(t);
        }
         
    // Function to find the Longest palindromic
    // string formed from concatenation of prefix
    // and suffix of a given string
        static string LongestPrefixSuffixPallindrome(string s)
        {
            int length = 0;
            int n = s.Length;
 
            for (int i = 0, j = n - 1; i < j; i++, j--)
            {
                if (s[i] != s[j])
                {
                    break;
                }
                length++;
            }
 
            string ans = s.Substring(0, length);
            string remaining = s.Substring(length, n - (2 * length));
 
            if (remaining.Length > 0)
            {
                int longestPrefix = RemainingStringLongestPallindrome(remaining);
                string reverse = new string(remaining.Reverse().ToArray());
                int longestSuffix = RemainingStringLongestPallindrome(reverse);
 
                if (longestPrefix > longestSuffix)
                {
                    ans += remaining.Substring(0, longestPrefix);
                }
                else
                {
                    ans += reverse.Substring(0, longestSuffix);
                }
            }
 
            ans += s.Substring(n - length, length);
 
            return ans;
        }
 
        static void Main(string[] args)
        {
            string str = "rombobinnimor";
 
            Console.WriteLine(LongestPrefixSuffixPallindrome(str));
            Console.ReadLine();
        }
    }
}

Output: 
rominnimor

 

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


Article Tags :