Given string str we need to tell minimum characters to be added in front of the string to make string palindrome.
Examples:
Input : str = "ABC"
Output : 2
We can make above string palindrome as "CBABC"
by adding 'B' and 'C' at front.
Input : str = "AACECAAAA";
Output : 2
We can make above string palindrome as AAAACECAAAA
by adding two A's at front of string.
Naive approach: Start checking the string each time if it is a palindrome and if not, then delete the last character and check again. When the string gets reduced to either a palindrome or an empty string then the number of characters deleted from the end till now will be the answer as those characters could have been inserted at the beginning of the original string in the order which will make the string a palindrome.
Below is the implementation of the above approach:
C++
#include<bits/stdc++.h>
using namespace std;
bool ispalindrome(string s)
{
int l = s.length();
int j;
for ( int i = 0, j = l - 1; i <= j; i++, j--)
{
if (s[i] != s[j])
return false ;
}
return true ;
}
int main()
{
string s = "BABABAA" ;
int cnt = 0;
int flag = 0;
while (s.length()>0)
{
if (ispalindrome(s))
{
flag = 1;
break ;
}
else
{
cnt++;
s.erase(s.begin() + s.length() - 1);
}
}
if (flag)
cout << cnt;
}
|
Java
class GFG {
static boolean ispalindrome(String s) {
int l = s.length();
for ( int i = 0 , j = l - 1 ; i <= j; i++, j--) {
if (s.charAt(i) != s.charAt(j)) {
return false ;
}
}
return true ;
}
public static void main(String[] args) {
String s = "BABABAA" ;
int cnt = 0 ;
int flag = 0 ;
while (s.length() > 0 ) {
if (ispalindrome(s)) {
flag = 1 ;
break ;
} else {
cnt++;
s = s.substring( 0 , s.length() - 1 );
}
}
if (flag == 1 ) {
System.out.println(cnt);
}
}
}
|
Python 3
def ispalindrome(s):
l = len (s)
i = 0
j = l - 1
while i < = j:
if (s[i] ! = s[j]):
return False
i + = 1
j - = 1
return True
if __name__ = = "__main__" :
s = "BABABAA"
cnt = 0
flag = 0
while ( len (s) > 0 ):
if (ispalindrome(s)):
flag = 1
break
else :
cnt + = 1
s = s[: - 1 ]
if (flag):
print (cnt)
|
C#
using System;
public class GFG {
static bool ispalindrome(String s) {
int l = s.Length;
for ( int i = 0, j = l - 1; i <= j; i++, j--) {
if (s[i] != s[j]) {
return false ;
}
}
return true ;
}
public static void Main() {
String s = "BABABAA" ;
int cnt = 0;
int flag = 0;
while (s.Length > 0) {
if (ispalindrome(s)) {
flag = 1;
break ;
} else {
cnt++;
s = s.Substring(0, s.Length - 1);
}
}
if (flag == 1) {
Console.WriteLine(cnt);
}
}
}
|
Javascript
<script>
function ispalindrome(s) {
let l = s.length;
let j;
for (let i = 0, j = l - 1; i <= j; i++, j--) {
if (s[i] != s[j])
return false ;
}
return true ;
}
let s = "BABABAA" ;
let cnt = 0;
let flag = 0;
while (s.length > 0)
{
if (ispalindrome(s)) {
flag = 1;
break ;
}
else {
cnt++;
s = s.substring(0, s.length - 1);
}
}
if (flag)
document.write(cnt);
</script>
|
Time complexity: O(n2)
Auxiliary Space: O(1)
Thank you Sanny Kumar for suggesting this approach.
Efficient approach: We can solve this problem efficiently in O(n) time using lps array of KMP algorithm.
First, we concat string by concatenating the given string, a special character and reverse of given string then we will get lps array for this concatenated string, recall that each index of lps array represents the longest proper prefix which is also a suffix. We can use this lps array to solve the problem.
For string = AACECAAAA
Concatenated String = AACECAAAA$AAAACECAA
LPS array will be {0, 1, 0, 0, 0, 1, 2, 2, 2,
0, 1, 2, 2, 2, 3, 4, 5, 6, 7}
Here we are only interested in the last value of this lps array because it shows us the largest suffix of the reversed string that matches the prefix of the original string i.e these many characters already satisfy the palindrome property. Finally minimum number of characters needed to make the string a palindrome is the length of the input string minus the last entry of our lps array.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
vector< int > computeLPSArray(string str)
{
int M = str.length();
vector< int > lps(M);
int len = 0;
lps[0] = 0;
int i = 1;
while (i < M)
{
if (str[i] == str[len])
{
len++;
lps[i] = len;
i++;
}
else
{
if (len != 0)
{
len = lps[len-1];
}
else
{
lps[i] = 0;
i++;
}
}
}
return lps;
}
int getMinCharToAddedToMakeStringPalin(string str)
{
string revStr = str;
reverse(revStr.begin(), revStr.end());
string concat = str + "$" + revStr;
vector< int > lps = computeLPSArray(concat);
return (str.length() - lps.back());
}
int main()
{
string str = "AACECAAAA" ;
cout << getMinCharToAddedToMakeStringPalin(str);
return 0;
}
|
Java
import java.util.*;
class GFG
{
public static int [] computeLPSArray(String str)
{
int n = str.length();
int lps[] = new int [n];
int i = 1 , len = 0 ;
lps[ 0 ] = 0 ;
while (i < n)
{
if (str.charAt(i) == str.charAt(len))
{
len++;
lps[i] = len;
i++;
}
else
{
if (len != 0 )
{
len = lps[len - 1 ];
}
else
{
lps[i] = 0 ;
i++;
}
}
}
return lps;
}
static int getMinCharToAddedToMakeStringPalin(String str)
{
StringBuilder s = new StringBuilder();
s.append(str);
String rev = s.reverse().toString();
s.reverse().append( "$" ).append(rev);
int lps[] = computeLPSArray(s.toString());
return str.length() - lps[s.length() - 1 ];
}
public static void main(String args[])
{
String str = "AACECAAAA" ;
System.out.println(getMinCharToAddedToMakeStringPalin(str));
}
}
|
Python3
def computeLPSArray(string):
M = len (string)
lps = [ None ] * M
length = 0
lps[ 0 ] = 0
i = 1
while i < M:
if string[i] = = string[length]:
length + = 1
lps[i] = length
i + = 1
else :
if length ! = 0 :
length = lps[length - 1 ]
else :
lps[i] = 0
i + = 1
return lps
def getMinCharToAddedToMakeStringPalin(string):
revStr = string[:: - 1 ]
concat = string + "$" + revStr
lps = computeLPSArray(concat)
return len (string) - lps[ - 1 ]
if __name__ = = "__main__" :
string = "AACECAAAA"
print (getMinCharToAddedToMakeStringPalin(string))
|
C#
using System;
using System.Text;
public class GFG{
public static int [] computeLPSArray( string str)
{
int n = str.Length;
int [] lps = new int [n];
int i = 1, len = 0;
lps[0] = 0;
while (i < n)
{
if (str[i] == str[len])
{
len++;
lps[i] = len;
i++;
}
else
{
if (len != 0)
{
len = lps[len - 1];
}
else
{
lps[i] = 0;
i++;
}
}
}
return lps;
}
static int getMinCharToAddedToMakeStringPalin( string str)
{
char [] s = str.ToCharArray();
Array.Reverse( s );
string rev = new string (s);
string concat= str + "$" + rev;
int [] lps = computeLPSArray(concat);
return str.Length - lps[concat.Length - 1];
}
static public void Main (){
string str = "AACECAAAA" ;
Console.WriteLine(getMinCharToAddedToMakeStringPalin(str));
}
}
|
Javascript
<script>
function computeLPSArray(str)
{
let M = str.length;
let lps = new Array(M);
let len = 0;
lps[0] = 0;
let i = 1;
while (i < M)
{
if (str[i] == str[len])
{
len++;
lps[i] = len;
i++;
}
else
{
if (len != 0)
{
len = lps[len-1];
}
else
{
lps[i] = 0;
i++;
}
}
}
return lps;
}
function getMinCharToAddedToMakeStringPalin(str)
{
let revStr = str.split( '' ).reverse().join( '' );
let concat = str + "$" + revStr;
let lps = computeLPSArray(concat);
return (str.length - lps[lps.length-1]);
}
let str = "AACECAAAA" ;
document.write(getMinCharToAddedToMakeStringPalin(str));
</script>
|
Time Complexity: O(n)
Auxiliary Space: O(n)
Another approach using “Two Pointers”:-
- Initialize two pointers start and end to the beginning and end of the string, respectively.
- While start is less than end, if the characters at the start and end pointers are equal, move the start pointer one position to the right and the end pointer one position to the left. If the characters are not equal, increment the res variable (which keeps track of the number of characters that need to be added) and reset the start and end pointers to the beginning and end of the string with a reduced number of characters.
- When start is no longer less than end, return the value of res as the minimum number of characters that need to be added to the front of the string to make it a palindrome.
Here’s the code for above approach:
C++
#include <iostream>
#include <string>
using namespace std;
class Solution {
public :
int addMinChar(string str1) {
int n = str1.length();
int start = 0;
int end = n - 1;
int res = 0;
while (start < end) {
if (str1[start] == str1[end]) {
start++;
end--;
}
else {
res++;
start = 0;
end = n - res - 1;
}
}
return res;
}
};
int main() {
Solution sol;
string str = "AACECAAAA" ;
cout << sol.addMinChar(str) << endl;
return 0;
}
|
Java
class Solution {
public int addMinChar(String str1) {
int n = str1.length();
int start = 0 ;
int end = n - 1 ;
int res = 0 ;
while (start < end) {
if (str1.charAt(start) == str1.charAt(end)) {
start++;
end--;
}
else {
res++;
start = 0 ;
end = n - res - 1 ;
}
}
return res;
}
}
class Main {
public static void main(String[] args) {
Solution sol = new Solution();
String str = "AACECAAAA" ;
System.out.println(sol.addMinChar(str));
}
}
|
Python3
class Solution:
def addMinChar( self , str1):
n = len (str1)
start = 0
end = n - 1
res = 0
while start < end:
if str1[start] = = str1[end]:
start + = 1
end - = 1
else :
res + = 1
start = 0
end = n - res - 1
return res
if __name__ = = "__main__" :
string = "AACECAAAA"
print (addMinChar(string))
|
C#
using System;
public class Solution {
public int AddMinChar( string str1) {
int n = str1.Length;
int start = 0;
int end = n - 1;
int res = 0;
while (start < end) {
if (str1[start] == str1[end]) {
start++;
end--;
} else {
res++;
start = 0;
end = n - res - 1;
}
}
return res;
}
}
public class Program {
public static void Main() {
string s = "AACECAAAA" ;
Solution solution = new Solution();
int result = solution.AddMinChar(s);
Console.WriteLine(result);
}
}
|
Javascript
class Solution {
addMinChar(str1) {
let n = str1.length;
let start = 0;
let end = n - 1;
let res = 0;
while (start < end) {
if (str1[start] === str1[end]) {
start++;
end--;
} else {
res++;
start = 0;
end = n - res - 1;
}
}
return res;
}
}
let s = "AACECAAAA" ;
let solution = new Solution();
let result = solution.addMinChar(s);
console.log(result);
|
The time complexity of this algorithm is O(n), where n is the length of the input string.
The space complexity is O(1), since the algorithm uses only constant extra space.
Another Approach: Similar to KMP algorithm, we have Z-Algorithm. It can solve this problem efficiently in O(n) time using Z array of Z algorithm.
First, we concat string by concatenating the given string, a special character and reverse of given string then we will get Z array for this concatenated string, recall that each index of Z array represents the length of the longest substring starting at index i, which is also a proper prefix. We can use this Z array to solve the problem.
For string = AACECAAAA
Concatenated String = AACECAAAA$AAAACECAA
Z array will be {0, 1, 0, 0, 0, 2, 2, 2, 1, 0, 2, 2, 7, 1, 0, 0, 0, 2, 1}
After calculating the Z array, we will traverse the Z array, now, we are only interested in the values in which the Z[i] is equal to the length of the substring starting from i and ending at the concat.size() – 1, this works because this substring will also be a suffix. Finally minimum number of characters needed to make the string a palindrome is the length of the input string mminum the maximum of the Z array, where the above condition satisifies.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
vector< int > ComputeZArray(string str)
{
vector< int > Z(str.size(), 0);
int l = 0, r = 0;
for ( int i = 1; i < str.size(); i++){
if (i <= r){
Z[i] = min(Z[i - l], r - i + 1);
}
while (str[0 + Z[i]] == str[i + Z[i]]){
Z[i]++;
}
if (i + Z[i] - 1 > r){
l = i;
r = i + Z[i] - 1;
}
}
return Z;
}
int getMinCharToAddedToMakeStringPalin(string str) {
int n= str.size();
string revStr = str;
reverse(begin(revStr), end(revStr));
string concat = str + "$" + revStr;
int charactersToRemove = INT_MIN;
vector< int > Z = ComputeZArray(concat);
for ( int i = 0; i < Z.size(); i++){
if (Z[i] == concat.size() - i) charactersToRemove = max(charactersToRemove, Z[i]);
}
return n - charactersToRemove;
}
int main()
{
string str = "AACECAAAA" ;
cout << getMinCharToAddedToMakeStringPalin(str);
return 0;
}
|
Java
import java.util.*;
public class GFG {
public static List<Integer> computeZArray(String str)
{
List<Integer> Z = new ArrayList<>(
Collections.nCopies(str.length(), 0 ));
int l = 0 ,
r = 0 ;
for ( int i = 1 ; i < str.length(); i++) {
if (i <= r) {
Z.set(i, Math.min(Z.get(i - l), r - i + 1 ));
}
while (i + Z.get(i) < str.length()
&& str.charAt(Z.get(i))
== str.charAt(i + Z.get(i))) {
Z.set(i, Z.get(i) + 1 );
}
if (i + Z.get(i) - 1 > r) {
l = i;
r = i + Z.get(i) - 1 ;
}
}
return Z;
}
public static int
getMinCharToAddedToMakeStringPalin(String str)
{
int n = str.length();
String revStr
= new StringBuilder(str).reverse().toString();
String concat = str + "$" + revStr;
int charactersToRemove = Integer.MIN_VALUE;
List<Integer> Z = computeZArray(concat);
for ( int i = 0 ; i < Z.size(); i++) {
if (Z.get(i) == concat.length() - i) {
charactersToRemove = Math.max(
charactersToRemove, Z.get(i));
}
}
return n - charactersToRemove;
}
public static void main(String[] args)
{
String str = "AACECAAAA" ;
System.out.println(
getMinCharToAddedToMakeStringPalin(
str));
}
}
|
Python3
def compute_z_array(string):
n = len (string)
Z = [ 0 ] * n
l = 0
r = 0
for i in range ( 1 , n):
if i < = r:
Z[i] = min (Z[i - l], r - i + 1 )
while i + Z[i] < n and string[Z[i]] = = string[i + Z[i]]:
Z[i] + = 1
if i + Z[i] - 1 > r:
l = i
r = i + Z[i] - 1
return Z
def get_min_char_to_make_string_palindrome(string):
n = len (string)
rev_str = string[:: - 1 ]
concat = string + "$" + rev_str
characters_to_remove = float ( '-inf' )
Z = compute_z_array(concat)
for i in range ( len (Z)):
if Z[i] = = len (concat) - i:
characters_to_remove = max (characters_to_remove, Z[i])
return n - characters_to_remove
str = "AACECAAAA"
print (get_min_char_to_make_string_palindrome( str ))
|
C#
using System;
using System.Collections.Generic;
public class GFG {
public static List< int > ComputeZArray( string str)
{
List< int > Z = new List< int >( new int [str.Length]);
int l = 0,
r = 0;
for ( int i = 1; i < str.Length; i++) {
if (i <= r) {
Z[i] = Math.Min(Z[i - l], r - i + 1);
}
while (i + Z[i] < str.Length
&& str[Z[i]] == str[i + Z[i]]) {
Z[i]++;
}
if (i + Z[i] - 1 > r) {
l = i;
r = i + Z[i] - 1;
}
}
return Z;
}
public static int
GetMinCharToAddedToMakeStringPalin( string str)
{
int n = str.Length;
char [] charArray = str.ToCharArray();
Array.Reverse(charArray);
string revStr = new string (charArray);
string concat = str + "$" + revStr;
int charactersToRemove = int .MinValue;
List< int > Z = ComputeZArray(concat);
for ( int i = 0; i < Z.Count; i++) {
if (Z[i] == concat.Length - i) {
charactersToRemove
= Math.Max(charactersToRemove, Z[i]);
}
}
return n - charactersToRemove;
}
public static void Main( string [] args)
{
string str = "AACECAAAA" ;
Console.WriteLine(
GetMinCharToAddedToMakeStringPalin(
str));
}
}
|
Javascript
<script>
function computeZArray(str) {
const n = str.length;
const Z = new Array(n).fill(0);
let l = 0;
let r = 0;
for (let i = 1; i < n; i++) {
if (i <= r) {
Z[i] = Math.min(Z[i - l], r - i + 1);
}
while (str[i + Z[i]] === str[Z[i]]) {
Z[i]++;
}
if (i + Z[i] - 1 > r) {
l = i;
r = i + Z[i] - 1;
}
}
return Z;
}
function getMinCharToAddedToMakeStringPalin(str) {
const n = str.length;
const revStr = str.split( '' ).reverse().join( '' );
const concat = str + '$' + revStr;
let charactersToRemove = Number.MIN_SAFE_INTEGER;
const Z = computeZArray(concat);
for (let i = 0; i < Z.length; i++) {
if (Z[i] === concat.length - i) {
charactersToRemove = Math.max(charactersToRemove, Z[i]);
}
}
return n - charactersToRemove;
}
const str = "AACECAAAA" ;
document.write(getMinCharToAddedToMakeStringPalin(str));
</script>
|
Time Complexity: O(n)
Auxiliary Space: O(n)
If you like GeeksforGeeks and would like to contribute, you can also write an article using write.geeksforgeeks.org or mail your article to review-team@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.
Please write comments if you find anything incorrect, or if you want to share more information about the topic discussed above.
Feeling lost in the world of random DSA topics, wasting time without progress? It's time for a change! Join our DSA course, where we'll guide you on an exciting journey to master DSA efficiently and on schedule.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 geeks!
Last Updated :
09 Oct, 2023
Like Article
Save Article