Minimum number of Appends needed to make a string palindrome
Last Updated :
17 Apr, 2023
Given a string s we need to tell minimum characters to be appended (insertion at the end) to make a string palindrome.
Examples:
Input : s = "abede"
Output : 2
We can make string palindrome as "abedeba"
by adding ba at the end of the string.
Input : s = "aabb"
Output : 2
We can make string palindrome as"aabbaa"
by adding aa at the end of the string.
The solution can be achieved by removing characters from the beginning of the string one by one and checking if the string is palindrome or not.
For Example, consider the above string, s = “abede”.
We check if the string is palindrome or not.
The result is false, then we remove the character from the beginning of a string and now string becomes “bede”.
We check if the string is palindrome or not. The result is again false, then we remove the character from the beginning of a string and now the string becomes “ede”.
We check if the string is palindrome or not. The result is true, so the output becomes 2 which is the number of characters removed from the string.
Implementation:
C++
#include <cstring>
#include <iostream>
using namespace std;
bool isPalindrome(string str)
{
int len = str.length();
if (len == 1)
return true ;
string::iterator ptr1 = str.begin();
string::iterator ptr2 = str.end() - 1;
while (ptr2 > ptr1) {
if (*ptr1 != *ptr2)
return false ;
ptr1++;
ptr2--;
}
return true ;
}
int noOfAppends(string s)
{
if (isPalindrome(s))
return 0;
s.erase(s.begin());
return 1 + noOfAppends(s);
}
int main()
{
string s = "abede" ;
cout << noOfAppends(s) << endl;
return 0;
}
|
C
#include<stdio.h>
#include<string.h>
#include<stdbool.h>
bool isPalindrome( char *str)
{
int len = strlen (str);
if (len == 1)
return true ;
char *ptr1 = str;
char *ptr2 = str+len-1;
while (ptr2 > ptr1)
{
if (*ptr1 != *ptr2)
return false ;
ptr1++;
ptr2--;
}
return true ;
}
int noOfAppends( char s[])
{
if (isPalindrome(s))
return 0;
s++;
return 1 + noOfAppends(s);
}
int main()
{
char s[] = "abede" ;
printf ( "%d\n" , noOfAppends(s));
return 0;
}
|
Java
class GFG
{
static boolean isPalindrome( char []str)
{
int len = str.length;
if (len == 1 )
return true ;
int ptr1 = 0 ;
int ptr2 = len- 1 ;
while (ptr2 >= ptr1)
{
if (str[ptr1] != str[ptr2])
return false ;
ptr1++;
ptr2--;
}
return true ;
}
static int noOfAppends(String s)
{
if (isPalindrome(s.toCharArray()))
return 0 ;
s=s.substring( 1 );
return 1 + noOfAppends(s);
}
public static void main(String arr[])
{
String s = "abede" ;
System.out.printf( "%d\n" , noOfAppends(s));
}
}
|
Python3
def isPalindrome( Str ):
Len = len ( Str )
if ( Len = = 1 ):
return True
ptr1 = 0
ptr2 = Len - 1
while (ptr2 > ptr1):
if ( Str [ptr1] ! = Str [ptr2]):
return False
ptr1 + = 1
ptr2 - = 1
return True
def noOfAppends(s):
if (isPalindrome(s)):
return 0
del s[ 0 ]
return 1 + noOfAppends(s)
se = "abede"
s = [i for i in se]
print (noOfAppends(s))
|
C#
using System;
class GFG
{
static Boolean isPalindrome( char []str)
{
int len = str.Length;
if (len == 1)
return true ;
char ptr1 = str[0];
char ptr2 = str[len-1];
while (ptr2 > ptr1)
{
if (ptr1 != ptr2)
return false ;
ptr1++;
ptr2--;
}
return true ;
}
static int noOfAppends(String s)
{
if (isPalindrome(s.ToCharArray()))
return 0;
s=s.Substring(1);
return 1 + noOfAppends(s);
}
public static void Main(String []arr)
{
String s = "abede" ;
Console.Write( "{0}\n" , noOfAppends(s));
}
}
|
Javascript
<script>
function isPalindrome(str)
{
let len = str.length;
if (len == 1)
return true ;
let ptr1 = 0;
let ptr2 = len-1;
while (ptr2 >= ptr1)
{
if (str[ptr1] != str[ptr2])
return false ;
ptr1++;
ptr2--;
}
return true ;
}
function noOfAppends(s)
{
if (isPalindrome(s.split( "" )))
return 0;
s=s.substring(1);
return 1 + noOfAppends(s);
}
let s = "abede" ;
document.write(noOfAppends(s));
</script>
|
Time Complexity: O(n2)
Auxiliary Space: O(n)
Efficient Approach:
We also have an algorithm taking the help of the Knuth Morris Pratt Algorithm which is O(n) Time Complexity.
The basic idea behind the approach is that we calculate the largest substring from the end can be calculated and the length of the string minus this value is the minimum number of appends. The logic is intuitive, we need not append the palindrome and only those which do not form the palindrome. To find this largest palindrome from the end, we reverse the string, calculate the DFA and reverse the string again(thus gaining back the original string) and find the final state, which represents the number of matches of the string with the revered string and hence we get the largest substring that is a palindrome from the end, in O(n) time.
Below is the implementation of the above approach:
C++
#include <algorithm>
#include <iostream>
#include <string>
using namespace std;
class kmp_numeric {
private :
int n;
int ** dfa;
public :
kmp_numeric(string& s)
{
n = s.length();
int c = 256;
dfa = new int *[n];
for ( int i = 0; i < n; i++)
dfa[i] = new int ;
int x = 0;
for ( int i = 0; i < c; i++)
dfa[0][i] = 0;
dfa[0][s[0]] = 1;
for ( int i = 1; i < n; i++) {
for ( int j = 0; j < c; j++) {
dfa[i][j] = dfa[x][j];
}
dfa[i][s[i]] = i + 1;
x = dfa[x][s[i]];
}
}
int longest_overlap(string& query)
{
int ql = query.length();
int state = 0;
for ( int i = 0; i < ql; i++) {
state = dfa[state][query[i]];
}
return state;
}
};
int min_appends(string& s)
{
reverse(s.begin(), s.end());
kmp_numeric kmp = s;
reverse(s.begin(), s.end());
int ans = s.length() - kmp.longest_overlap(s);
return ans;
}
int main()
{
string s = "deep" ;
string t = "sososososos" ;
cout << min_appends(s) << endl;
cout << min_appends(t) << endl;
}
|
Java
import java.io.*;
import java.util.*;
class KMPNumeric {
private int n;
private int [][] dfa;
KMPNumeric(String s)
{
n = s.length();
int c = 256 ;
dfa = new int [n];
int x = 0 ;
for ( int i = 0 ; i < c; i++)
dfa[ 0 ][i] = 0 ;
dfa[ 0 ][s.charAt( 0 )] = 1 ;
for ( int i = 1 ; i < n; i++) {
for ( int j = 0 ; j < c; j++) {
dfa[i][j] = dfa[x][j];
}
dfa[i][s.charAt(i)] = i + 1 ;
x = dfa[x][s.charAt(i)];
}
}
public int longestOverlap(String query)
{
int ql = query.length();
int state = 0 ;
for ( int i = 0 ; i < ql; i++) {
state = dfa[state][query.charAt(i)];
}
return state;
}
}
class GFG {
static int minAppends(String s)
{
String reversed
= new StringBuilder(s).reverse().toString();
KMPNumeric kmp = new KMPNumeric(reversed);
int overlap = kmp.longestOverlap(s);
int ans = s.length() - overlap;
return ans;
}
public static void main(String[] args)
{
String s = "deep" ;
String t = "sososososos" ;
System.out.println(minAppends(s));
System.out.println(minAppends(t));
}
}
|
Python3
class kmp_numeric:
def __init__( self , s: str ):
n = len (s)
c = 256
self .dfa = [[ 0 for _ in range (c)] for _ in range (n)]
x = 0
self .dfa[ 0 ][ ord (s[ 0 ])] = 1
for i in range ( 1 , n):
for j in range (c):
self .dfa[i][j] = self .dfa[x][j]
self .dfa[i][ ord (s[i])] = i + 1
x = self .dfa[x][ ord (s[i])]
def longest_overlap( self , query: str ) - > int :
ql = len (query)
state = 0
for i in range (ql):
state = self .dfa[state][ ord (query[i])]
return state
def min_appends(s: str ) - > int :
s_reversed = s[:: - 1 ]
kmp = kmp_numeric(s_reversed)
s_reversed = s_reversed[:: - 1 ]
ans = len (s) - kmp.longest_overlap(s_reversed)
return ans
if __name__ = = '__main__' :
s = "deep"
t = "sososososos"
print (min_appends(s))
print (min_appends(t))
|
Javascript
class kmp_numeric {
constructor(s) {
let n = s.length;
let c = 256;
this .dfa = Array.from(Array(n), () => new Array(c).fill(0));
let x = 0;
this .dfa[0][s.charCodeAt(0)] = 1;
for (let i = 1; i < n; i++) {
for (let j = 0; j < c; j++) {
this .dfa[i][j] = this .dfa[x][j];
}
this .dfa[i][s.charCodeAt(i)] = i + 1;
x = this .dfa[x][s.charCodeAt(i)];
}
}
longest_overlap(query) {
let ql = query.length;
let state = 0;
for (let i = 0; i < ql; i++) {
state = this .dfa[state][query.charCodeAt(i)];
}
return state;
}
}
function min_appends(s) {
let s_reversed = s.split( '' ).reverse().join( '' );
let kmp = new kmp_numeric(s_reversed);
s_reversed = s_reversed.split( '' ).reverse().join( '' );
let ans = s.length - kmp.longest_overlap(s_reversed);
return ans;
}
let s = "deep" ;
let t = "sososososos" ;
console.log(min_appends(s));
console.log(min_appends(t));
|
C#
using System;
class KMPNumeric
{
private int n;
private int [][] dfa;
public KMPNumeric( string s)
{
n = s.Length;
int c = 256;
dfa = new int [n][];
for ( int i = 0; i < n; i++)
dfa[i] = new int ;
int x = 0;
for ( int i = 0; i < c; i++)
dfa[0][i] = 0;
dfa[0][s[0]] = 1;
for ( int i = 1; i < n; i++)
{
for ( int j = 0; j < c; j++)
{
dfa[i][j] = dfa[x][j];
}
dfa[i][s[i]] = i + 1;
x = dfa[x][s[i]];
}
}
public int LongestOverlap( string query)
{
int ql = query.Length;
int state = 0;
for ( int i = 0; i < ql; i++)
{
state = dfa[state][query[i]];
}
return state;
}
}
class MinimumAppends
{
public static int MinAppends( string s)
{
char [] charArray = s.ToCharArray();
Array.Reverse(charArray);
s = new string (charArray);
KMPNumeric kmp = new KMPNumeric(s);
charArray = s.ToCharArray();
Array.Reverse(charArray);
s = new string (charArray);
int ans = s.Length - kmp.LongestOverlap(s);
return ans;
}
static void Main( string [] args)
{
string s = "deep" ;
string t = "sososososos" ;
Console.WriteLine(MinAppends(s));
Console.WriteLine(MinAppends(t));
}
}
|
Suggestion by: Pratik Priyadarsan
Time Complexity: O(n2)
Auxiliary Space: O(n2)
Related Article :
Dynamic Programming | Set 28 (Minimum insertions to form a palindrome)
Like Article
Suggest improvement
Share your thoughts in the comments
Please Login to comment...