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.
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();
}
}
} |
rominnimor
Time Complexity: O(N), where N is the length of the given string.
Auxiliary Space: O(N).