Open In App

Palindrome by Front Insertion

Last Updated : 26 Jul, 2025
Comments
Improve
Suggest changes
Like Article
Like
Report

Given a string s consisting of only lowercase English letters, find the minimum number of characters that need to be added to the front of s to make it a palindrome.
Note: A palindrome is a string that reads the same forward and backward.

Examples: 

Input: s = "abc"
Output: 2
Explanation: We can make above string palindrome as "cbabc", by adding 'b' and 'c' at front.

Input: s = "aacecaaaa"
Output: 2
Explanation: We can make above string palindrome as "aaaacecaaaa" by adding two a's at front of string.

[Naive Approach] Checking all prefixes - O(n^2) Time and O(1) Space

The idea is based on the observation that we need to find the longest prefix from given string which is also a palindrome. Then minimum front characters to be added to make given string palindrome will be the remaining characters.

characters-to-add-at-front-for-Palindrome
C++
#include <iostream>
using namespace std;

// function to check if the substring s[i...j] is a palindrome
bool isPalindrome(string &s, int i, int j) {
    while (i < j) {
      
        // if characters at the ends are not equal, 
        // it's not a palindrome
        if (s[i] != s[j]) {
            return false;
        }
        i++;
        j--;
    }
    return true;
}

int minChar(string &s) {
    int cnt = 0;
    int i = s.size() - 1;
    
    // iterate from the end of the string, checking for the 
    // longestpalindrome starting from the beginning
    while (i >= 0 && !isPalindrome(s, 0, i)) {
        
        i--;
        cnt++;
    }
    
    return cnt;
}

int main() {
    string s = "aacecaaaa";
    cout << minChar(s);
    return 0;
}
C
#include <stdio.h>
#include <stdbool.h>
#include <string.h>

// function to check if the substring s[i...j] is a palindrome
bool isPalindrome(char s[], int i, int j) {
    while (i < j) {
        
        // if characters at the ends are not the same, 
        // it's not a palindrome
        if (s[i] != s[j]) {
            return false;
        }
        i++;
        j--;
    }
    return true;
}

int minChar(char s[]) {
    int cnt = 0;
    int i = strlen(s) - 1;
    
    // iterate from the end of the string, checking for the 
    // longest palindrome starting from the beginning
    while (i >= 0 && !isPalindrome(s, 0, i)) {
        
        i--;
        cnt++;
    }
    
    return cnt;
}

int main() {
    
    char s[] = "aacecaaaa";
    printf("%d", minChar(s));
    return 0;
}
Java
class GfG {

    // function to check if the substring 
    // s[i...j] is a palindrome
    static boolean isPalindrome(String s, int i, int j) {
        while (i < j) {
            
            // if characters at the ends are not the same, 
            // it's not a palindrome
            if (s.charAt(i) != s.charAt(j)) {
                return false;
            }
            i++;
            j--;
        }
        return true;
    }

    static int minChar(String s) {
        int cnt = 0;
        int i = s.length() - 1;
        
        // iterate from the end of the string, checking for the 
        // longest palindrome starting from the beginning
        while (i >= 0 && !isPalindrome(s, 0, i)) {
            i--;
            cnt++;
        }
        
        return cnt;
    }

    public static void main(String[] args) {
        String s = "aacecaaaa";
        System.out.println(minChar(s));
    }
}
Python
# function to check if the substring s[i...j] is a palindrome
def isPalindrome(s, i, j):
    while i < j:
        
        # if characters at the ends are not the same, 
        # it's not a palindrome
        if s[i] != s[j]:
            return False
        i += 1
        j -= 1
    return True

def minChar(s):
    cnt = 0
    i = len(s) - 1
    
    # iterate from the end of the string, checking for the 
    # longest palindrome starting from the beginning
    while i >= 0 and not isPalindrome(s, 0, i):
        
        i -= 1
        cnt += 1
    
    return cnt

if __name__ == "__main__":
    s = "aacecaaaa"
    print(minChar(s))
C#
using System;
class GfG {

    // function to check if the substring s[i...j] is a palindrome
    static bool isPalindrome(string s, int i, int j) {
        while (i < j) {
            
            // if characters at the ends are not the same, 
            // it's not a palindrome
            if (s[i] != s[j]) {
                return false;
            }
            i++;
            j--;
        }
        return true;
    }

    static int minChar(string s) {
        int cnt = 0;
        int i = s.Length - 1;
        
        // iterate from the end of the string, checking for the longest 
        // palindrome starting from the beginning
        while (i >= 0 && !isPalindrome(s, 0, i)) {
            i--;
            cnt++;
        }
        
        return cnt;
    }

    static void Main() {
        
        string s = "aacecaaaa";
        Console.WriteLine(minChar(s));
    }
}
JavaScript
// function to check if the substring s[i...j] is a palindrome
function isPalindrome(s, i, j) {
    while (i < j) {
        
        // if characters at the ends are not the same, 
        // it's not a palindrome
        if (s[i] !== s[j]) {
            return false;
        }
        i++;
        j--;
    }
    return true;
}

function minChar(s) {
    let cnt = 0;
    let i = s.length - 1;
    
    // iterate from the end of the string, checking for the
    // longest palindrome starting from the beginning
    while (i >= 0 && !isPalindrome(s, 0, i)) {
        
        i--;
        cnt++;
    }
    
    return cnt;
}

// Driver code
let s = "aacecaaaa";
console.log(minChar(s));

Output
2

[Expected Approach 1] Using lps array of KMP Algorithm - O(n) Time and O(n) Space

The key observation is that the longest palindromic prefix of a string becomes the longest palindromic suffix of its reverse.
Given a string s = "aacecaaaa", its reverse revS = "aaaacecaa". The longest palindromic prefix of s is "aacecaa".

To find this efficiently, we use the LPS array from the KMP algorithm. We concatenate the original string with a special character and its reverse: s + '$' + revS.
The LPS array for this combined string helps identify the longest prefix of s that matches a suffix of revS, which also represents the palindromic prefix of s.

The last value of the LPS array tells us how many characters already form a palindrome at the beginning. Thus, the minimum number of characters to add to make s a palindrome is s.length() - lps.back().

C++
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;

vector<int> computeLPSArray(string &pat) {
    int n = pat.length();
    vector<int> lps(n);

    // lps[0] is always 0
    lps[0] = 0;
    int len = 0;

    // loop calculates lps[i] for i = 1 to M-1
    int i = 1;
    while (i < n) {

        // if the characters match, increment len
        // and set lps[i]
        if (pat[i] == pat[len]) {
            len++;
            lps[i] = len;
            i++;
        }

        // if there is a mismatch
        else {

            // if len is not zero, update len to
            // the last known prefix length
            if (len != 0) {
                len = lps[len - 1];
            }

            // no prefix matches, set lps[i] to 0
            else {
                lps[i] = 0;
                i++;
            }
        }
    }
    return lps;
}

// returns minimum character to be added at
// front to make string palindrome
int minChar(string &s) {
    int n = s.length();
    string rev = s;
    reverse(rev.begin(), rev.end());

    // get concatenation of string, special character
    // and reverse string
    s = s + "$" + rev;

    //  get LPS array of this concatenated string
    vector<int> lps = computeLPSArray(s);

    // by subtracting last entry of lps vector from
    // string length, we will get our result
    return (n - lps.back());
}

int main() {
    string s = "aacecaaaa";
    cout << minChar(s);
    return 0;
}
Java
import java.util.ArrayList;
class GfG {

    static int[] computeLPSArray(String pat) {
        int n = pat.length();
        int[] lps = new int[n];

        // lps[0] is always 0
        lps[0] = 0;
        int len = 0;

        // loop calculates lps[i] for i = 1 to n-1
        int i = 1;
        while (i < n) {

            // if the characters match, increment len
            // and set lps[i]
            if (pat.charAt(i) == pat.charAt(len)) {
                len++;
                lps[i] = len;
                i++;
            }

            // if there is a mismatch
            else {

                // if len is not zero, update len to
                // the last known prefix length
                if (len != 0) {
                    len = lps[len - 1];
                }

                // no prefix matches, set lps[i] to 0
                else {
                    lps[i] = 0;
                    i++;
                }
            }
        }
        return lps;
    }

    // returns minimum character to be added at
    // front to make string palindrome
    static int minChar(String s) {
        int n = s.length();
        String rev
            = new StringBuilder(s).reverse().toString();

        // get concatenation of string, special character
        // and reverse string
        s = s + "$" + rev;

        // get LPS array of this concatenated string
        int[] lps = computeLPSArray(s);

        // by subtracting last entry of lps array from
        // string length, we will get our result
        return (n - lps[lps.length - 1]);
    }

    public static void main(String[] args) {
        String s = "aacecaaaa";
        System.out.println(minChar(s));
    }
}
Python
def computeLPSArray(pat):
    n = len(pat)
    lps = [0] * n

    # lps[0] is always 0
    len_lps = 0

    # loop calculates lps[i] for i = 1 to n-1
    i = 1
    while i < n:
      
        # if the characters match, increment len
        # and set lps[i]
        if pat[i] == pat[len_lps]:
            len_lps += 1
            lps[i] = len_lps
            i += 1
        
        # if there is a mismatch
        else:
          
            # if len is not zero, update len to 
            # the last known prefix length
            if len_lps != 0:
                len_lps = lps[len_lps - 1]
                
			# no prefix matches, set lps[i] to 0
            else:
                lps[i] = 0
                i += 1
    return lps

# returns minimum character to be added at
# front to make string palindrome
def minChar(s):
    n = len(s)
    rev = s[::-1]

    # get concatenation of string, special character
    # and reverse string
    s = s + "$" + rev

    # get LPS array of this concatenated string
    lps = computeLPSArray(s)

    # by subtracting last entry of lps array from
    # string length, we will get our result
    return n - lps[-1]

if __name__ == "__main__":
    s = "aacecaaaa"
    print(minChar(s))
C#
using System;

class GfG {

    static int[] computeLPSArray(string pat) {
        int n = pat.Length;
        int[] lps = new int[n];

        // lps[0] is always 0
        lps[0] = 0;
        int len = 0;

        // loop calculates lps[i] for i = 1 to n-1
        int i = 1;
        while (i < n) {

            // if the characters match, increment len
            // and set lps[i]
            if (pat[i] == pat[len]) {
                len++;
                lps[i] = len;
                i++;
            }

            // if there is a mismatch
            else {

                // if len is not zero, update len to
                // the last known prefix length
                if (len != 0) {
                    len = lps[len - 1];
                }

                // no prefix matches, set lps[i] to 0
                else {
                    lps[i] = 0;
                    i++;
                }
            }
        }
        return lps;
    }

    // minimum character to be added at
    // front to make string palindrome
    static int minChar(string s) {
        int n = s.Length;
        char[] charArray = s.ToCharArray();
        Array.Reverse(charArray);
        string rev = new string(charArray);

        // get concatenation of string, special character
        // and reverse string
        s = s + "$" + rev;

        // get LPS array of this concatenated string
        int[] lps = computeLPSArray(s);

        // by subtracting last entry of lps array from
        // string length, we will get our result
        return n - lps[lps.Length - 1];
    }

    static void Main() {
        string s = "aacecaaaa";
        Console.WriteLine(minChar(s));
    }
}
JavaScript
function computeLPSArray(pat) {
    let n = pat.length;
    let lps = new Array(n).fill(0);

    // lps[0] is always 0
    let len = 0;

    // loop calculates lps[i] for i = 1 to n-1
    let i = 1;
    while (i < n) {

        // if the characters match, increment len
        // and set lps[i]
        if (pat[i] === pat[len]) {
            len++;
            lps[i] = len;
            i++;
        }

        // if there is a mismatch
        else {

            // if len is not zero, update len to
            // the last known prefix length
            if (len !== 0) {
                len = lps[len - 1];
            }

            // no prefix matches, set lps[i] to 0
            else {
                lps[i] = 0;
                i++;
            }
        }
    }
    return lps;
}

// returns minimum character to be added at
// front to make string palindrome
function minChar(s) {
    let n = s.length;
    let rev = s.split("").reverse().join("");

    // get concatenation of string, special character
    // and reverse string
    s = s + "$" + rev;

    // get LPS array of this concatenated string
    let lps = computeLPSArray(s);

    // by subtracting last entry of lps array from
    // string length, we will get our result
    return n - lps[lps.length - 1];
}

// Driver Code
let s = "aacecaaaa";
console.log(minChar(s));

Output
2

[Expected Approach 2] Using Manacher's Algorithm

The idea is to use Manacher’s algorithm to efficiently find all palindromic substrings in linear time.
We transform the string by inserting special characters (#) to handle both even and odd length palindromes uniformly.
After preprocessing, we scan from the end of the original string and use the palindrome radius array to check if the prefix s[0...i] is a palindrome. The first such index i gives us the longest palindromic prefix, and we return n - (i + 1) as the minimum characters to add.

C++
#include <iostream>
#include <vector>
#include <string>
using namespace std;

// manacher's algorithm for finding longest 
// palindromic substrings
class manacher {
public:
    // array to store palindrome lengths centered 
    // at each position
    vector<int> p;
    // modified string with separators and sentinels
    string ms;         

    manacher(string &s) {
        ms = "@";
        for (char c : s) {
            ms += "#" + string(1, c);
        }
        ms += "#$";
        runManacher();
    }

    // core Manacher's algorithm
    void runManacher() {
        int n = ms.size();
        p.assign(n, 0);
        int l = 0, r = 0;

        for (int i = 1; i < n - 1; ++i) {
            if (i < r)
                p[i] = min(r - i, p[r + l - i]);

            // expand around the current center
            while (ms[i + 1 + p[i]] == ms[i - 1 - p[i]])
                ++p[i];

            // update center if palindrome goes beyond
            // current right boundary
            if (i + p[i] > r) {
                l = i - p[i];
                r = i + p[i];
            }
        }
    }

    // returns the length of the longest palindrome
    // centered at given position
    int getLongest(int cen, int odd) {
        int pos = 2 * cen + 2 + !odd;
        return p[pos];
    }

    // checks whether substring s[l...r] is a palindrome
    bool check(int l, int r) {
        int len = r - l + 1;
        int longest = getLongest((l + r) / 2, len % 2);
        return len <= longest;
    }
};

// returns the minimum number of characters to add at the 
// front to make the given string a palindrome
int minChar(string &s) {
    int n = s.size();
    manacher m(s);

    // scan from the end to find the longest 
    // palindromic prefix
    for (int i = n - 1; i >= 0; --i) {
        if (m.check(0, i))
            return n - (i + 1);
    }

    return n - 1;
}

int main() {
    string s = "aacecaaaa";
    cout << minChar(s) << endl;
    return 0;
}
Java
class GfG {
    
    // manacher's algorithm for finding longest 
    // palindromic substrings
    static class manacher {
        // array to store palindrome lengths centered 
        // at each position
        int[] p;
        // modified string with separators and sentinels
        String ms;

        manacher(String s) {
            StringBuilder sb = new StringBuilder("@");
            for (char c : s.toCharArray()) {
                sb.append("#").append(c);
            }
            sb.append("#$");
            ms = sb.toString();
            runManacher();
        }

        // core Manacher's algorithm
        void runManacher() {
            int n = ms.length();
            p = new int[n];
            int l = 0, r = 0;

            for (int i = 1; i < n - 1; ++i) {
                if (i < r)
                    p[i] = Math.min(r - i, p[r + l - i]);

                // expand around the current center
                while (ms.charAt(i + 1 + p[i]) == ms.charAt(i - 1 - p[i]))
                    p[i]++;

                // update center if palindrome goes beyond 
                // current right boundary
                if (i + p[i] > r) {
                    l = i - p[i];
                    r = i + p[i];
                }
            }
        }

        // returns the length of the longest palindrome 
        // centered at given position
        int getLongest(int cen, int odd) {
            int pos = 2 * cen + 2 + (odd == 0 ? 1 : 0);
            return p[pos];
        }

        // checks whether substring s[l...r] is a palindrome
        boolean check(int l, int r) {
            int len = r - l + 1;
            int longest = getLongest((l + r) / 2, len % 2);
            return len <= longest;
        }
    }

    // returns the minimum number of characters to add at the 
    // front to make the given string a palindrome
    static int minChar(String s) {
        int n = s.length();
        manacher m = new manacher(s);

        // scan from the end to find the longest 
        // palindromic prefix
        for (int i = n - 1; i >= 0; --i) {
            if (m.check(0, i))
                return n - (i + 1);
        }

        return n - 1;
    }

    public static void main(String[] args) {
        String s = "aacecaaaa";
        System.out.println(minChar(s));
    }
}
Python
# manacher's algorithm for finding longest 
# palindromic substrings
class manacher:
    
    # array to store palindrome lengths centered 
    # at each position
    def __init__(self, s):

        # modified string with separators and sentinels
        self.ms = "@"
        for c in s:
            self.ms += "#" + c
        self.ms += "#$"
        self.p = []
        self.runManacher()

    # core Manacher's algorithm
    def runManacher(self):
        n = len(self.ms)
        self.p = [0] * n
        l = r = 0

        for i in range(1, n - 1):
            if i < r:
                self.p[i] = min(r - i, self.p[r + l - i])

            # expand around the current center
            while self.ms[i + 1 + self.p[i]] == self.ms[i - 1 - self.p[i]]:
                self.p[i] += 1

            # update center if palindrome goes beyond 
            # current right boundary
            if i + self.p[i] > r:
                l = i - self.p[i]
                r = i + self.p[i]

    # returns the length of the longest palindrome 
    # centered at given position
    def getLongest(self, cen, odd):
        pos = 2 * cen + 2 + (0 if odd else 1)
        return self.p[pos]

    # checks whether substring s[l...r] is a palindrome
    def check(self, l, r):
        length = r - l + 1
        longest = self.getLongest((l + r) // 2, length % 2)
        return length <= longest

# returns the minimum number of characters to add at the 
# front to make the given string a palindrome
def minChar(s):
    n = len(s)
    m = manacher(s)

    # scan from the end to find the longest 
    # palindromic prefix
    for i in range(n - 1, -1, -1):
        if m.check(0, i):
            return n - (i + 1)

    return n - 1

if __name__ == "__main__":
    s = "aacecaaaa"
    print(minChar(s))
C#
using System;

class GfG {
    
    // manacher's algorithm for finding longest 
    // palindromic substrings
    class manacher {
        // array to store palindrome lengths centered 
        // at each position
        public int[] p;
        // modified string with separators and sentinels
        public string ms;

        public manacher(string s) {
            ms = "@";
            foreach (char c in s) {
                ms += "#" + c;
            }
            ms += "#$";
            runManacher();
        }

        // core Manacher's algorithm
        void runManacher() {
            int n = ms.Length;
            p = new int[n];
            int l = 0, r = 0;

            for (int i = 1; i < n - 1; ++i) {
                if (i < r)
                    p[i] = Math.Min(r - i, p[r + l - i]);

                // expand around the current center
                while (ms[i + 1 + p[i]] == ms[i - 1 - p[i]])
                    p[i]++;

                // update center if palindrome goes beyond 
                // current right boundary
                if (i + p[i] > r) {
                    l = i - p[i];
                    r = i + p[i];
                }
            }
        }

        // returns the length of the longest palindrome 
        // centered at given position
        public int getLongest(int cen, int odd) {
            int pos = 2 * cen + 2 + (odd == 0 ? 1 : 0);
            return p[pos];
        }

        // checks whether substring s[l...r] is a palindrome
        public bool check(int l, int r) {
            int len = r - l + 1;
            int longest = getLongest((l + r) / 2, len % 2);
            return len <= longest;
        }
    }

    // returns the minimum number of characters to add at the 
    // front to make the given string a palindrome
    static int minChar(string s) {
        int n = s.Length;
        manacher m = new manacher(s);

        // scan from the end to find the longest 
        // palindromic prefix
        for (int i = n - 1; i >= 0; --i) {
            if (m.check(0, i))
                return n - (i + 1);
        }

        return n - 1;
    }

    static void Main() {
        string s = "aacecaaaa";
        Console.WriteLine(minChar(s));
    }
}
JavaScript
// manacher's algorithm for finding longest 
// palindromic substrings
class manacher {
    
    // array to store palindrome lengths centered 
    // at each position
    constructor(s) {
        // modified string with separators and sentinels
        this.ms = "@";
        for (let c of s) {
            this.ms += "#" + c;
        }
        this.ms += "#$";
        this.p = [];
        this.runManacher();
    }

    // core Manacher's algorithm
    runManacher() {
        const n = this.ms.length;
        this.p = new Array(n).fill(0);
        let l = 0, r = 0;

        for (let i = 1; i < n - 1; ++i) {
            if (i < r)
                this.p[i] = Math.min(r - i, this.p[r + l - i]);

            // expand around the current center
            while (this.ms[i + 1 + this.p[i]] === this.ms[i - 1 - this.p[i]])
                this.p[i]++;

            // update center if palindrome goes beyond 
            // current right boundary
            if (i + this.p[i] > r) {
                l = i - this.p[i];
                r = i + this.p[i];
            }
        }
    }

    // returns the length of the longest palindrome 
    // centered at given position
    getLongest(cen, odd) {
        const pos = 2 * cen + 2 + (odd === 0 ? 1 : 0);
        return this.p[pos];
    }

    // checks whether substring s[l...r] is a palindrome
    check(l, r) {
        const len = r - l + 1;
        const longest = this.getLongest(Math.floor((l + r) / 2), len % 2);
        return len <= longest;
    }
}

// returns the minimum number of characters to add at the 
// front to make the given string a palindrome
function minChar(s) {
    const n = s.length;
    const m = new manacher(s);

    // scan from the end to find the longest 
    // palindromic prefix
    for (let i = n - 1; i >= 0; --i) {
        if (m.check(0, i))
            return n - (i + 1);
    }

    return n - 1;
}

// Driver Code
const s = "aacecaaaa";
console.log(minChar(s));

Output
2

Time Complexity: O(n), manacher's algorithm runs in linear time by expanding palindromes at each center without revisiting characters, and the prefix check loop performs O(1) operations per character over n characters.
Auxiliary Space: O(n), used for the modified string and the palindrome length array p[], both of which grow linearly with the input size.


Minimum Characters to Add for Palindrome
Visit Course explore course icon
Article Tags :
Practice Tags :

Similar Reads