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

14 Mar, 2022
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.  
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.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.The concatenation of s[0, l], ans and s[n-l, n-l-1] is the longest palindromic substring.
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.
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.
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:
C++
Python3
Javascript
// C++ implementation of the above approach#include <bits/stdc++.h>using namespace std; // Function used to calculate the longest prefix// which is also a suffixint 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 prefixint 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 stringstring 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 Codeint main(){    string str = "rombobinnimor";     cout << longestPrefixSuffixPallindrome(str)         << endl;}
# Python3 implementation of# the above approach # Function used to calculate# the longest prefix# which is also a suffixdef 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 prefixdef 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 stringdef 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 Codeif __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 suffixfunction 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 prefixfunction 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 stringfunction 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>
rominnimor
 
Time Complexity: O(N), where N is the length of the given string.Auxiliary Space: O(N).
ukasp
varshagumber28
arorakashish0911
pankajsharmagfg
shinjanpatra
Algorithms
Competitive Programming
Strings
Strings
Algorithms
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.