Longest palindromic String formed using concatenation of given strings in any order
Given an array of strings arr[] of the same length, the task is to find the longest palindromic string that can be made using the concatenation of strings in any order.
Examples:
Input: arr[] = {“aba”, “aba”}
Output: abaaba
Input: arr[] = {“abc”, “dba”, “kop”, “cba”, “abd”}
Output: abcdbaabdcba
Approach:
- Find all the pairs of strings which are reverse of each other and store them in two different arrays pair1[] and pair2 separately and delete those pairs from the original array.
- Find any palindromic string s1 in the array.
- Join all the strings together of the array pair1[] into s2
- Join all the strings together of the array pair2[] in reverse order into s3
- Concatenate the strings s2 + s1 + s3 together to get longest palindromic string.
Below is the implementation of the above approach.
C++
#include <bits/stdc++.h>
using namespace std;
void longestPalindrome(string a[],
int n)
{
string pair1[n];
string pair2[n];
int r = 0;
for ( int i = 0; i < n; i++) {
string s = a[i];
reverse(s.begin(), s.end());
for ( int j = i + 1; j < n; j++) {
if (a[i] != "" && a[j] != "" ) {
if (s == a[j]) {
pair1[r] = a[i];
pair2[r++] = a[j];
a[i] = "" ;
a[j] = "" ;
break ;
}
}
}
}
string s1 = "" ;
for ( int i = 0; i < n; i++) {
string s = a[i];
reverse(a[i].begin(), a[i].end());
if (a[i] != "" ) {
if (a[i] == s) {
s1 = a[i];
break ;
}
}
}
string ans = "" ;
for ( int i = 0; i < r; i++) {
ans = ans + pair1[i];
}
if (s1 != "" ) {
ans = ans + s1;
}
for ( int j = r - 1; j >= 0; j--) {
ans = ans + pair2[j];
}
cout << ans << endl;
}
int main()
{
string a1[2] = { "aba" , "aba" };
int n1 = sizeof (a1) / sizeof (a1[0]);
longestPalindrome(a1, n1);
string a2[5] = { "abc" , "dba" , "kop" ,
"abd" , "cba" };
int n2 = sizeof (a2) / sizeof (a2[0]);
longestPalindrome(a2, n2);
}
|
Java
class GFG
{
static void longestPalindrome(String a[],
int n)
{
String []pair1 = new String[n];
String []pair2 = new String[n];
int r = 0 ;
for ( int i = 0 ; i < n; i++)
{
String s = a[i];
s = reverse(s);
for ( int j = i + 1 ; j < n; j++)
{
if (a[i] != "" && a[j] != "" )
{
if (s.equals(a[j]))
{
pair1[r] = a[i];
pair2[r++] = a[j];
a[i] = "" ;
a[j] = "" ;
break ;
}
}
}
}
String s1 = "" ;
for ( int i = 0 ; i < n; i++)
{
String s = a[i];
a[i] = reverse(a[i]);
if (a[i] != "" )
{
if (a[i].equals(s))
{
s1 = a[i];
break ;
}
}
}
String ans = "" ;
for ( int i = 0 ; i < r; i++)
{
ans = ans + pair1[i];
}
if (s1 != "" )
{
ans = ans + s1;
}
for ( int j = r - 1 ; j >= 0 ; j--)
{
ans = ans + pair2[j];
}
System.out.print(ans + "\n" );
}
static String reverse(String input)
{
char [] a = input.toCharArray();
int l, r = a.length - 1 ;
for (l = 0 ; l < r; l++, r--)
{
char temp = a[l];
a[l] = a[r];
a[r] = temp;
}
return String.valueOf(a);
}
public static void main(String[] args)
{
String []a1 = { "aba" , "aba" };
int n1 = a1.length;
longestPalindrome(a1, n1);
String []a2 = { "abc" , "dba" , "kop" ,
"abd" , "cba" };
int n2 = a2.length;
longestPalindrome(a2, n2);
}
}
|
Python3
def longestPalindrome(a, n):
pair1 = [ 0 ] * n
pair2 = [ 0 ] * n
r = 0
for i in range (n):
s = a[i]
s = s[:: - 1 ]
for j in range (i + 1 , n):
if (a[i] ! = " " and a[j] != " "):
if (s = = a[j]):
pair1[r] = a[i]
pair2[r] = a[j]
r + = 1
a[i] = ""
a[j] = ""
break
s1 = ""
for i in range (n):
s = a[i]
a[i] = a[i][:: - 1 ]
if (a[i] ! = ""):
if (a[i] = = s):
s1 = a[i]
break
ans = ""
for i in range (r):
ans = ans + pair1[i]
if (s1 ! = ""):
ans = ans + s1
for j in range (r - 1 , - 1 , - 1 ):
ans = ans + pair2[j]
print (ans)
a1 = [ "aba" , "aba" ]
n1 = len (a1)
longestPalindrome(a1, n1)
a2 = [ "abc" , "dba" , "kop" , "abd" , "cba" ]
n2 = len (a2)
longestPalindrome(a2, n2)
|
C#
using System;
class GFG
{
static void longestPalindrome(String []a,
int n)
{
String []pair1 = new String[n];
String []pair2 = new String[n];
int r = 0;
for ( int i = 0; i < n; i++)
{
String s = a[i];
s = reverse(s);
for ( int j = i + 1; j < n; j++)
{
if (a[i] != "" && a[j] != "" )
{
if (s.Equals(a[j]))
{
pair1[r] = a[i];
pair2[r++] = a[j];
a[i] = "" ;
a[j] = "" ;
break ;
}
}
}
}
String s1 = "" ;
for ( int i = 0; i < n; i++)
{
String s = a[i];
a[i] = reverse(a[i]);
if (a[i] != "" )
{
if (a[i].Equals(s))
{
s1 = a[i];
break ;
}
}
}
String ans = "" ;
for ( int i = 0; i < r; i++)
{
ans = ans + pair1[i];
}
if (s1 != "" )
{
ans = ans + s1;
}
for ( int j = r - 1; j >= 0; j--)
{
ans = ans + pair2[j];
}
Console.Write(ans + "\n" );
}
static String reverse(String input)
{
char [] a = input.ToCharArray();
int l, r = a.Length - 1;
for (l = 0; l < r; l++, r--)
{
char temp = a[l];
a[l] = a[r];
a[r] = temp;
}
return String.Join( "" ,a);
}
public static void Main(String[] args)
{
String []a1 = { "aba" , "aba" };
int n1 = a1.Length;
longestPalindrome(a1, n1);
String []a2 = { "abc" , "dba" , "kop" ,
"abd" , "cba" };
int n2 = a2.Length;
longestPalindrome(a2, n2);
}
}
|
Javascript
<script>
function longestPalindrome(a, n)
{
var pair1 = Array(n);
var pair2 = Array(n);
var r = 0;
for ( var i = 0; i < n; i++)
{
var s = a[i];
s = s.split( '' ).reverse().join( '' );
for ( var j = i + 1; j < n; j++)
{
if (a[i] != "" && a[j] != "" )
{
if (s == a[j])
{
pair1[r] = a[i];
pair2[r++] = a[j];
a[i] = "" ;
a[j] = "" ;
break ;
}
}
}
}
var s1 = "" ;
for ( var i = 0; i < n; i++)
{
var s = a[i];
a[i] = a[i].split( '' ).reverse().join( '' );
if (a[i] != "" )
{
if (a[i] == s)
{
s1 = a[i];
break ;
}
}
}
var ans = "" ;
for ( var i = 0; i < r; i++)
{
ans = ans + pair1[i];
}
if (s1 != "" )
{
ans = ans + s1;
}
for ( var j = r - 1; j >= 0; j--)
{
ans = ans + pair2[j];
}
document.write(ans + "<br>" );
}
var a1 = [ "aba" , "aba" ];
var n1 = a1.length;
longestPalindrome(a1, n1);
var a2 = [ "abc" , "dba" , "kop" ,
"abd" , "cba" ];
var n2 = a2.length;
longestPalindrome(a2, n2);
</script>
|
Output
abaaba
abcdbaabdcba
Time Complexity: O(N2)
Auxiliary Space: O(N)
Method 2
Approach: One point to note down is that basically there are two types of strings. First, the strings which are palindrome let us say pallString and second, the strings that are not palindrome let us say notPallString. We will store pallString in a hashmap pallMap and notPallString in hashmap notPallMap. Now assume we have an array ans[] which stores the final palindromic string inside it. We also have two pointers i and j such that i points to starting index of ans and j points to the last index of ans.
Now we will travel our given array, arr. If we get pallString then we will increase its frequency in pallMap. If we get notPallString then it is an interesting case. We will check if it’s reverse, reverse_notPallString exists in notPallMap or not. If reverse_notPallString exists in the notPallMap in that case notPallString and reverse_notpallString can be part of our ans array. So we will add notPallString at index i and reverse_notPallString at index j . We will also decrease the frequency of reverse_notPallString from our notPallMap. After this, we will increase i and decrease j. If reverse_notpallString does not exist in notPallMap, then we will increase the frequency of notPallString in notPallMap. Similarly, we will travel the whole array. After traveling the whole arr, pallMap will store the strings and their frequency which are palindromes on their own. So we will iterate over the pallMap. Assume we have the string pall_string and its frequency as freq as we are iterating the pallMap. Now while the freq > 1, we will add pall_string at index i and index j respectively, and will decrease the freq by 2. We will also increase i pointer and decrease j pointer. We will also maintain whether we got any odd freq or not because such pall_string does not require any other string to be part of ans array. So such pall can be at the center of our ans array .
After the above steps, our ans array will store the palindromic arrangements of arr.
Algorithm:
1) Maintain an array ans which will sore the palindromic strings. Pointer i will point to the starting of ans and j will point to the ending of ans
1) Iterate the array arr
2) If you got a pallString, then increase its frequency in the pallMap
3) If you got a notPallString, than
3.1) Check if its reverse reverse_notPallString exists in the notPallMap or not
3.2) If the reverse_notPallString exists in notPallMap then add noPallString at index i and reverse_notPallString at index j. Also decrease the frequency of reverse_notPallString from notPallMap. Increase i pointer and decrease j pointer after the addition of the strings in ans .
3.3) If the reverse_notPallString does not exist in notPallMap then increase the frequency of notPallString in notPallMap
4) After traveling the arr, travel the pallMap as it will have palindromic strings pall_string with its frequency as freq
5) Now, while the freq > 1, add pall_string at index i and j. Also, decrease the freq by 2.
6) Note if any freq is odd or not because such pall_string, let us say centre_string can be at the center of our array arr as it is a palindrome and does not require any reverse to contribute to the ans .
7) Travel ans and, and store the valid strings in your result (skipping null values)
Below is the implementation of the above approach.
C++
#include <iostream>
#include <string>
#include <unordered_map>
#include <vector>
using namespace std;
void solve(string arr[], int n);
int main()
{
string a1[] = { "aba" , "aba" };
int n1 = sizeof (a1) / sizeof (a1[0]);
solve(a1, n1);
string a2[] = { "abc" , "dba" , "kop" , "abd" , "cba" };
int n2 = sizeof (a2) / sizeof (a2[0]);
solve(a2, n2);
return 0;
}
void solve(string arr[], int n)
{
vector<string> ans(n);
int i = 0, j = n - 1;
unordered_map<string, int > pallMap;
unordered_map<string, int > notPallMap;
for ( int k = 0; k < n; k++) {
string str1 = arr[k];
string str2 = string(str1.rbegin(), str1.rend());
if (str1 == str2) {
pallMap[str1]++;
}
else {
int freq = notPallMap[str2];
if (freq == 0) {
notPallMap[str1]++;
}
else {
ans[i] = str1;
ans[j] = str2;
i++;
j--;
notPallMap[str2]--;
}
}
}
string odd;
for ( auto & kk : pallMap) {
string pall_string = kk.first;
int freq = kk.second;
if (freq % 2 == 1) {
while (freq > 1) {
ans[i++] = pall_string;
ans[j--] = pall_string;
freq -= 2;
}
if (odd.empty()) {
odd = pall_string;
}
}
else {
while (freq > 0) {
ans[i++] = pall_string;
ans[j--] = pall_string;
freq -= 2;
}
}
}
if (!odd.empty()) {
ans[i++] = odd;
}
string res;
for ( auto & temp : ans) {
if (!temp.empty()) {
res += temp;
}
}
cout << res << endl;
}
string reverse(string input)
{
int l, r = input.size() - 1;
for (l = 0; l < r; l++, r--) {
char temp = input[l];
input[l] = input[r];
input[r] = temp;
}
return input;
}
|
Java
import java.util.*;
import java.io.*;
public class GFG {
public static void main(String[] args)
{
String []a1 = { "aba" , "aba" };
int n1 = a1.length;
solve(a1, n1);
String []a2 = { "abc" , "dba" , "kop" ,
"abd" , "cba" };
int n2 = a2.length;
solve(a2, n2);
}
static void solve( String[] arr , int n )
{
String ans[] = new String[n] ;
int i = 0 , j = n- 1 ;
HashMap< String , Integer > pallMap = new HashMap<>() ;
HashMap< String , Integer > notPallMap = new HashMap<>() ;
for ( int k = 0 ; k < n ; k++)
{
String str1 = arr[k] ;
String str2 = reverse(str1) ;
if (str1.equals(str2))
{
pallMap.put( str1, pallMap.getOrDefault( pallMap , 0 ) + 1 ) ;
} else
{
int freq = notPallMap.getOrDefault( str2 , 0 ) ;
if ( freq == 0 )
{
notPallMap.put( str1, notPallMap.getOrDefault( str1 , 0 ) + 1 ) ;
} else
{
ans[i] = str1 ;
ans[j] = str2 ;
i++;j--;
notPallMap.put( str2 , freq - 1 ) ;
}
}
}
String odd = null ;
for ( Map.Entry<String , Integer> kk : pallMap.entrySet())
{
String pall_string = kk.getKey() ;
int freq = kk.getValue();
if ( freq % 2 == 1 )
{
while ( freq > 1 )
{
ans[i++] = pall_string ;
ans[j--] = pall_string ;
freq-= 2 ;
}
if ( odd == null )
{
odd = pall_string ;
}
} else
{
while ( freq > 0 )
{
ans[i++] = pall_string ;
ans[j--] = pall_string ;
freq-= 2 ;
}
}
}
if ( odd != null ) ans[i++] = odd ;
String res = "" ;
for ( String temp :ans )
{
if ( temp != null )
{
res += temp ;
}
}
System.out.println(res);
}
static String reverse(String input)
{
char [] a = input.toCharArray();
int l, r = a.length - 1 ;
for (l = 0 ; l < r; l++, r--)
{
char temp = a[l];
a[l] = a[r];
a[r] = temp;
}
return String.valueOf(a);
}
}
|
Python
from collections import defaultdict
def solve(arr, n):
ans = [ None ] * n
i, j = 0 , n - 1
pallMap = defaultdict( int )
notPallMap = defaultdict( int )
for k in range (n):
str1 = arr[k]
str2 = str1[:: - 1 ]
if str1 = = str2:
pallMap[str1] + = 1
else :
freq = notPallMap.get(str2, 0 )
if freq = = 0 :
notPallMap[str1] + = 1
else :
ans[i] = str1
ans[j] = str2
i + = 1
j - = 1
notPallMap[str2] - = 1
odd = None
for pall_string, freq in pallMap.items():
if freq % 2 = = 1 :
while freq > 1 :
ans[i] = pall_string
ans[j] = pall_string
i + = 1
j - = 1
freq - = 2
if odd is None :
odd = pall_string
else :
while freq > 0 :
ans[i] = pall_string
ans[j] = pall_string
i + = 1
j - = 1
freq - = 2
if odd is not None :
ans[i] = odd
res = ''.join(x for x in ans if x is not None )
print (res)
if __name__ = = '__main__' :
a1 = [ "aba" , "aba" ]
n1 = len (a1)
solve(a1, n1)
a2 = [ "abc" , "dba" , "kop" , "abd" , "cba" ]
n2 = len (a2)
solve(a2, n2)
|
C#
using System;
using System.Collections.Generic;
namespace GFG
{
class Program
{
static void Main( string [] args)
{
string [] a1 = { "aba" , "aba" };
int n1 = a1.Length;
Solve(a1, n1);
string [] a2 = { "abc" , "dba" , "kop" , "abd" , "cba" };
int n2 = a2.Length;
Solve(a2, n2);
}
static void Solve( string [] arr, int n)
{
string [] ans = new string [n];
int i = 0, j = n - 1;
Dictionary< string , int > pallMap = new Dictionary< string , int >();
Dictionary< string , int > notPallMap = new Dictionary< string , int >();
for ( int k = 0; k < n; k++)
{
string str1 = arr[k];
string str2 = Reverse(str1);
if (str1.Equals(str2))
{
pallMap[str1] = pallMap.GetValueOrDefault(str1) + 1;
}
else
{
int freq = notPallMap.GetValueOrDefault(str2);
if (freq == 0)
{
notPallMap[str1] = notPallMap.GetValueOrDefault(str1) + 1;
}
else
{
ans[i] = str1;
ans[j] = str2;
i++;
j--;
notPallMap[str2] = freq - 1;
}
}
}
string odd = null ;
foreach (KeyValuePair< string , int > kvp in pallMap)
{
string pallString = kvp.Key;
int freq = kvp.Value;
if (freq % 2 == 1)
{
while (freq > 1)
{
ans[i++] = pallString;
ans[j--] = pallString;
freq -= 2;
}
if (odd == null )
{
odd = pallString;
}
}
else
{
while (freq > 0)
{
ans[i++] = pallString;
ans[j--] = pallString;
freq -= 2;
}
}
}
if (odd != null )
{
ans[i++] = odd;
}
string res = string .Join( "" , ans);
Console.WriteLine(res);
}
static string Reverse( string input)
{
char [] a = input.ToCharArray();
int l, r = a.Length - 1;
for (l = 0; l < r; l++, r--)
{
char temp = a[l];
a[l] = a[r];
a[r] = temp;
}
return new string (a);
}
}
}
|
Javascript
function solve(arr, n) {
let ans = new Array(n).fill( null );
let i = 0, j = n - 1;
let pallMap = new Map();
let notPallMap = new Map();
let odd = null ;
for (let k = 0; k < n; k++) {
let str1 = arr[k];
let str2 = str1.split( '' ).reverse().join( '' );
if (str1 === str2) {
if (pallMap.has(str1)) {
pallMap.set(str1, pallMap.get(str1) + 1);
} else {
pallMap.set(str1, 1);
}
} else {
if (notPallMap.has(str2)) {
let freq = notPallMap.get(str2);
if (freq > 0) {
ans[i] = str1;
ans[j] = str2;
i++;
j--;
notPallMap.set(str2, freq - 1);
} else {
notPallMap.set(str1, notPallMap.get(str1) + 1);
}
} else {
notPallMap.set(str1, 1);
}
}
}
for (let [pall_string, freq] of pallMap.entries()) {
if (freq % 2 === 1) {
while (freq > 1) {
ans[i] = pall_string;
ans[j] = pall_string;
i++;
j--;
freq -= 2;
}
if (odd === null ) {
odd = pall_string;
}
} else {
while (freq > 0) {
ans[i] = pall_string;
ans[j] = pall_string;
i++;
j--;
freq -= 2;
}
}
}
if (odd !== null ) {
ans[i] = odd;
}
let res = ans.filter(x => x !== null ).join( '' );
console.log(res);
}
let a1 = [ "aba" , "aba" ];
let n1 = a1.length;
solve(a1, n1);
let a2 = [ "abc" , "dba" , "kop" , "abd" , "cba" ];
let n2 = a2.length;
solve(a2, n2);
|
Output
abaaba
abdcbaabcdba
Time Complexity : O(n)
Auxiliary Space : O(n)
Last Updated :
14 Sep, 2023
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...