Open In App

Minimum insertions to form shortest palindrome

Improve
Improve
Like Article
Like
Save
Share
Report

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++




// C++ program to find minimum number of insertions
// on left side to form a palindrome.
 
#include <bits/stdc++.h>
using namespace std;
 
// Returns true if a string str[st..end] is palindrome
bool isPalin(char str[], int st, int end)
{
    while (st < end) {
        if (str[st] != str[end])
            return false;
        st++;
        end--;
    }
    return true;
}
 
// Returns count of insertions on left side to make
// str[] a palindrome
int findMinInsert(char str[], int n)
{
    // Find the largest prefix of given string
    // that is palindrome.
    for (int i = n - 1; i >= 0; i--) {
        // Characters after the palindromic prefix
        // must be added at the beginning also to make
        // the complete string palindrome
        if (isPalin(str, 0, i))
            return (n - i - 1);
    }
}
 
// Driver program
int main()
{
    char Input[] = "JAVA";
    printf("%d", findMinInsert(Input, strlen(Input)));
    return 0;
}


Java




// Java program to find minimum number
// of insertions on left side to form
// a palindrome.
import java.util.*;
 
class GFG {
 
    // Returns true if a string
    // str[st..end] is palindrome
    static boolean isPalin(char[] str, int st, int end)
    {
        while (st < end) {
            if (str[st] != str[end])
                return false;
 
            st++;
            end--;
        }
        return true;
    }
 
    // Returns count of insertions on
    // left side to make str[] a palindrome
    static int findMinInsert(char[] str, int n)
    {
 
        // Find the largest prefix of given
        // string that is palindrome.
        for (int i = n - 1; i >= 0; i--) {
 
            // Characters after the palindromic
            // prefix must be added at the
            // beginning also to make the
            // complete string palindrome
            if (isPalin(str, 0, i))
                return (n - i - 1);
        }
        return 0;
    }
 
    // Driver Code
    public static void main(String[] args)
    {
        char[] Input = "JAVA".toCharArray();
 
        System.out.println(
            findMinInsert(Input, Input.length));
    }
}
 
// This code is contributed by pratham76


Python3




# Python3 program to find
# minimum number of insertions
# on left side to form a palindrome.
 
# Returns true if a string
# str[st..end] is palindrome
 
 
def isPalin(str, st, end):
 
    while (st < end):
 
        if (str[st] != str[end]):
            return False
        st += 1
        end--1
 
    return True
 
 
# Returns count of insertions
# on left side to make
# str[] a palindrome
def findMinInsert(str, n):
 
    # Find the largest
    # prefix of given string
    # that is palindrome.
    for i in range(n-1, -1, -1):
 
        # Characters after the
        # palindromic prefix must
        # be added at the beginning
        # also to make the complete
        # string palindrome
        if (isPalin(str, 0, i)):
            return (n - i - 1)
 
 
# Driver Code
Input = "JAVA"
print(findMinInsert(Input,
                    len(Input)))
 
# This code is contributed
# by Smitha


C#




// C# program to find minimum number
// of insertions on left side to form
// a palindrome.
using System;
using System.Text;
 
class GFG {
 
    // Returns true if a string
    // str[st..end] is palindrome
    static bool isPalin(char[] str, int st, int end)
    {
        while (st < end) {
            if (str[st] != str[end])
                return false;
 
            st++;
            end--;
        }
        return true;
    }
 
    // Returns count of insertions on
    // left side to make str[] a palindrome
    static int findMinInsert(char[] str, int n)
    {
 
        // Find the largest prefix of given string
        // that is palindrome.
        for (int i = n - 1; i >= 0; i--) {
 
            // Characters after the palindromic
            // prefix must be added at the
            // beginning also to make the
            // complete string palindrome
            if (isPalin(str, 0, i))
                return (n - i - 1);
        }
        return 0;
    }
 
    // Driver Code
    public static void Main(string[] args)
    {
        char[] Input = "JAVA".ToCharArray();
 
        Console.Write(findMinInsert(Input, Input.Length));
    }
}
 
// This code is contributed by rutvik_56


Javascript




<script>
// javascript program to find minimum number of insertions
// on left side to form a palindrome.
 
// Returns true if a string str[st..end] is palindrome
function isPalin(str,st,end)
{
    while (st < end)
    {
        if (str[st] != str[end])
            return false;
        st++;
        end--;
    }
    return true;
}
 
// Returns count of insertions on left side to make
// str[] a palindrome
function findMinInsert(str,n)
{
    // Find the largest prefix of given string
    // that is palindrome.
    for (let i = n - 1; i >= 0; i--)
    {       
        // Characters after the palindromic prefix
        // must be added at the beginning also to make
        // the complete string palindrome
        if (isPalin(str, 0, i))
            return (n - i - 1);
    }
}
 
    let Input = "JAVA";
    document.write(findMinInsert(Input,Input.length));
     
 // This code is contributed by vaibhavrabadiya07.  
</script>


Output

3

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;
// using kmp algorithm
int find_lps(string str)
{
    int n = str.length();
    vector<int> lps(n, 0); // initialized with 0
 
    int len = 0; // length of previous longest prefix suffix
    // the loop calculates lps[i] for i = 1 to M-1
    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 {
     
    // using kmp algorithm
    public static int find_lps(String str) {
        int n = str.length();
        int[] lps = new int[n];
 
        int len = 0; // length of previous longest prefix suffix
        // the loop calculates lps[i] for i = 1 to M-1
        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 {
 
  // using kmp algorithm
  public static int find_lps(string str) {
    int n = str.Length;
    int[] lps = new int[n];
 
    int len = 0; // length of previous longest prefix suffix
    // the loop calculates lps[i] for i = 1 to M-1
    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




// using kmp algorithm
function find_lps(str) {
    let n = str.length;
    let lps = new Array(n).fill(0); // initialized with 0
 
    let len = 0; // length of previous longest prefix suffix
    // the loop calculates lps[i] for i = 1 to M-1
    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);


Output

0

Time Complexity: O(N),
Auxiliary Space: O(N) where N is the length of newS.



Last Updated : 24 Feb, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads