Minimum insertions to form shortest palindrome
Given a string S, determine the least number of characters that should be added on to the left side of S so that the complete string becomes a palindrome.
Examples:
Input: S = "LOL"
Output: 0
LOL is already a palindrome
Input: S = "JAVA"
Output: 3
We need to add 3 characters to form AVAJAVA.
The idea is to find the longest palindromic prefix of given string. The count of characters after the prefix is our answer. The longest palindromic prefix can be found by looping from last char to first char. For example, in “JAVA”, the longest palindromic prefix is “J”, so we need to add remaining 3 at the beginning characters to form palindrome.
C++
#include <bits/stdc++.h>
using namespace std;
bool isPalin( char str[], int st, int end)
{
while (st < end) {
if (str[st] != str[end])
return false ;
st++;
end--;
}
return true ;
}
int findMinInsert( char str[], int n)
{
for ( int i = n - 1; i >= 0; i--) {
if (isPalin(str, 0, i))
return (n - i - 1);
}
}
int main()
{
char Input[] = "JAVA" ;
printf ( "%d" , findMinInsert(Input, strlen (Input)));
return 0;
}
|
Java
import java.util.*;
class GFG {
static boolean isPalin( char [] str, int st, int end)
{
while (st < end) {
if (str[st] != str[end])
return false ;
st++;
end--;
}
return true ;
}
static int findMinInsert( char [] str, int n)
{
for ( int i = n - 1 ; i >= 0 ; i--) {
if (isPalin(str, 0 , i))
return (n - i - 1 );
}
return 0 ;
}
public static void main(String[] args)
{
char [] Input = "JAVA" .toCharArray();
System.out.println(
findMinInsert(Input, Input.length));
}
}
|
Python3
def isPalin( str , st, end):
while (st < end):
if ( str [st] ! = str [end]):
return False
st + = 1
end - - 1
return True
def findMinInsert( str , n):
for i in range (n - 1 , - 1 , - 1 ):
if (isPalin( str , 0 , i)):
return (n - i - 1 )
Input = "JAVA"
print (findMinInsert( Input ,
len ( Input )))
|
C#
using System;
using System.Text;
class GFG {
static bool isPalin( char [] str, int st, int end)
{
while (st < end) {
if (str[st] != str[end])
return false ;
st++;
end--;
}
return true ;
}
static int findMinInsert( char [] str, int n)
{
for ( int i = n - 1; i >= 0; i--) {
if (isPalin(str, 0, i))
return (n - i - 1);
}
return 0;
}
public static void Main( string [] args)
{
char [] Input = "JAVA" .ToCharArray();
Console.Write(findMinInsert(Input, Input.Length));
}
}
|
Javascript
<script>
function isPalin(str,st,end)
{
while (st < end)
{
if (str[st] != str[end])
return false ;
st++;
end--;
}
return true ;
}
function findMinInsert(str,n)
{
for (let i = n - 1; i >= 0; i--)
{
if (isPalin(str, 0, i))
return (n - i - 1);
}
}
let Input = "JAVA" ;
document.write(findMinInsert(Input,Input.length));
</script>
|
Time Complexity: O(n2)
Auxiliary Space: O(1)
Thanks to Utkarsh Trivedi for suggesting this solution.
Optimized solution using the idea of KMP
Here we’ll preprocess the string and use the lps[] to skip the characters and store the longest palindromic prefix.
For example: s = "AABAACAABAA”,
lps[] is [0, 1, 0, 1, 2, 0, 1, 2, 3, 4, 5]
In the above example we clearly see that the lps[] can give the length of longest proper palindromic prefix. But here we need longest palindromic prefix not proper palindromic prefix. So, to handle this we can we can append the reverse of S in S.
For Example: s = ABBC
newS = "ABBC" + "#" + "CBBA"
lps[] for newS is [0 0 0 0 0 0 0 0 1 1]
As 1 is there at the end of lps[]. so our ans is 4 - 1 = 3
Using the above logic, we can get the solution in O(N) time only.
C++
#include <bits/stdc++.h>
using namespace std;
int find_lps(string str)
{
int n = str.length();
vector< int > lps(n, 0);
int len = 0;
int i = 1;
while (i < n) {
if (str[len] == str[i]) {
lps[i++] = ++len;
}
else {
if (len != 0)
len = lps[len - 1];
else
lps[i++] = 0;
}
}
return lps[n - 1];
}
int main()
{
string s = "AABAACAABAA" ;
string rev = s;
reverse(rev.begin(), rev.end());
string newS = s + "#" + rev;
int len = find_lps(newS);
cout << s.length() - len << endl;
return 0;
}
|
Java
import java.util.*;
public class Main {
public static int find_lps(String str) {
int n = str.length();
int [] lps = new int [n];
int len = 0 ;
int i = 1 ;
while (i < n) {
if (str.charAt(len) == str.charAt(i)) {
lps[i++] = ++len;
}
else {
if (len != 0 )
len = lps[len - 1 ];
else
lps[i++] = 0 ;
}
}
return lps[n - 1 ];
}
public static void main(String[] args) {
String s = "AABAACAABAA" ;
String rev = new StringBuilder(s).reverse().toString();
String newS = s + "#" + rev;
int len = find_lps(newS);
System.out.println(s.length() - len);
}
}
|
Python3
def find_lps(string):
n = len (string)
lps = [ 0 ] * n
length = 0
i = 1
while i < n:
if string[length] = = string[i]:
lps[i] = length + 1
i + = 1
length + = 1
else :
if length ! = 0 :
length = lps[length - 1 ]
else :
lps[i] = 0
i + = 1
return lps[n - 1 ]
s = "AABAACAABAA"
rev = s[:: - 1 ]
newS = s + "#" + rev
length = find_lps(newS)
print ( len (s) - length)
|
C#
using System;
public class MainClass {
public static int find_lps( string str) {
int n = str.Length;
int [] lps = new int [n];
int len = 0;
int i = 1;
while (i < n) {
if (str[len] == str[i]) {
lps[i++] = ++len;
}
else {
if (len != 0)
len = lps[len - 1];
else
lps[i++] = 0;
}
}
return lps[n - 1];
}
public static void Main() {
string s = "AABAACAABAA" ;
char [] charArray = s.ToCharArray();
Array.Reverse(charArray);
string rev = new string (charArray);
string newS = s + "#" + rev;
int len = find_lps(newS);
Console.WriteLine(s.Length - len);
}
}
|
Javascript
function find_lps(str) {
let n = str.length;
let lps = new Array(n).fill(0);
let len = 0;
let i = 1;
while (i < n) {
if (str[len] == str[i]) {
lps[i++] = ++len;
} else {
if (len != 0)
len = lps[len - 1];
else
lps[i++] = 0;
}
}
return lps[n - 1];
}
let s = "AABAACAABAA" ;
let rev = s.split( '' ).reverse().join( '' );
let newS = s + "#" + rev;
let len = find_lps(newS);
console.log(s.length - len);
|
Time Complexity: O(N),
Auxiliary Space: O(N) where N is the length of newS.
Last Updated :
24 Feb, 2023
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...