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

Given a 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.



  1. Find the longest prefix(say s[0, l]) which is also a palindrome of the suffix(say s[n-l, n-1]) of the string str. Prefix and Suffix don’t overlap.
  2. Out of the remaining substring(s[l+1, n-l-1]), find the longest palindromic substring(say ans) which is either a suffix or prefix of the remaining string.
  3. The concatenation of s[0, l], ans and s[n-l, n-l-1] is the longest palindromic substring.

Below is the implementation of the above approach:

filter_none

edit
close

play_arrow

link
brightness_4
code

// 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 whcih 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 greter 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;
}

chevron_right


Output:

rominnimor

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

competitive-programming-img




My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.