Open In App

Minimum number of Appends needed to make a string palindrome

Last Updated : 16 Nov, 2024
Comments
Improve
Suggest changes
Like Article
Like
Report

Given a string s, the task is to find the minimum characters to be appended (insertion at the end) to make a string palindrome. 

Examples: 

Input: s = “abede”
Output : 2
Explanation: We can make string palindrome as “abedeba” by adding ba at the end of the string.

Input: s = “aabb”
Output : 2
Explanation: We can make string palindrome as”aabbaa” by adding aa at the end of the string.

Check palindrome every time – O(n^2) Time and O(n) Space

The solution involves progressively removing characters from the beginning of the string, one by one, until the string becomes a palindrome. The answer will be total number of character removed.

For example, consider the string s = “abede”. We first check if the entire string is a palindrome, which it isn’t. Next, we remove the first character, resulting in the string “bede”. We check again, but it’s still not a palindrome. We then remove another character from the start, leaving “ede”. This time, the string is a palindrome. Therefore, the output is 2, representing the number of characters removed from the beginning to achieve a palindrome.

C++
// C++ code to find minimum number 
// of appends to make string Palindrome

#include <iostream>
using namespace std;

// Function to check if a given string is a palindrome
bool isPalindrome(string s) {
    int left = 0, right = s.length() - 1;
    while (left < right) {
        if (s[left] != s[right]) return false;
        left++;
        right--;
    }
    return true;
}

// Function to find the minimum number of 
// characters to remove from the beginning
int noOfAppends(string& s) {
    int n = s.length();
  
    // Remove characters from the start until 
  	// the string becomes a palindrome
    for (int i = 0; i < n; i++) {
        if (isPalindrome(s.substr(i))) {
          
          	// Return the number of characters removed
            return i; 
        }
    }
  
  	// If no palindrome is found, remove
  	// all but one character
    return n - 1; 
}

int main() {
    string s = "abede";
    int result = noOfAppends(s);
    cout <<  result << endl;
    return 0;
}
Java
// Java code to find minimum number 
// of appends to make string Palindrome

import java.util.*;

class GfG {
    
    // Function to check if a given string is a palindrome
    static boolean isPalindrome(String s) {
        int left = 0, right = s.length() - 1;
        while (left < right) {
            if (s.charAt(left) != s.charAt(right)) return false;
            left++;
            right--;
        }
        return true;
    }
    
    // Function to find the minimum number of 
    // characters to remove from the beginning
    static int noOfAppends(String s) {
        int n = s.length();
      
        // Remove characters from the start until 
        // the string becomes a palindrome
        for (int i = 0; i < n; i++) {
            if (isPalindrome(s.substring(i))) {
              
                // Return the number of characters removed
                return i;
            }
        }
        
        // If no palindrome is found, remove
      	// all but one character
        return n - 1;
    }

    public static void main(String[] args) {
        String s = "abede";
        int result = noOfAppends(s);
        System.out.println(result);
    }
}
Python
# Python code to find minimum number 
# of appends to make string Palindrome

# Function to check if a given string is a palindrome
def is_palindrome(s):
    left, right = 0, len(s) - 1
    while left < right:
        if s[left] != s[right]:
            return False
        left += 1
        right -= 1
    return True

# Function to find the minimum number of 
# characters to remove from the beginning
def no_of_appends(s):
    n = len(s)
    
    # Remove characters from the start until 
    # the string becomes a palindrome
    for i in range(n):
        if is_palindrome(s[i:]):
          
            # Return the number of characters
            # removed
            return i
    # If no palindrome is found, remove
    # all but one character
    return n - 1

if __name__ == "__main__":
    s = "abede"
    result = no_of_appends(s)
    print(result)
C#
// C# code to find minimum number 
// of appends to make string Palindrome

using System;

class GfG {
    
    // Function to check if a given string 
  	// is a palindrome
    static bool IsPalindrome(string s) {
        int left = 0, right = s.Length - 1;
        while (left < right) {
            if (s[left] != s[right]) return false;
            left++;
            right--;
        }
        return true;
    }

    // Function to find the minimum number of 
    // characters to remove from the beginning
    static int NoOfAppends(string s) {
        int n = s.Length;
      
        // Remove characters from the start until 
        // the string becomes a palindrome
        for (int i = 0; i < n; i++) {
            if (IsPalindrome(s.Substring(i))) {
              
                // Return the number of characters
              	// removed
                return i;
            }
        }
        
        // If no palindrome is found, remove all but 
      	// one character
        return n - 1;
    }

    static void Main(string[] args) {
        string s = "abede";
        int result = NoOfAppends(s);
        Console.WriteLine(result);
    }
}
JavaScript
// JavaScript code to find minimum number 
// of appends to make string Palindrome

// Function to check if a given string is a palindrome
function isPalindrome(s) {
    let left = 0, right = s.length - 1;
    while (left < right) {
        if (s[left] !== s[right]) return false;
        left++;
        right--;
    }
    return true;
}

// Function to find the minimum number of 
// characters to remove from the beginning
function noOfAppends(s) {
    let n = s.length;
    
    // Remove characters from the start until 
    // the string becomes a palindrome
    for (let i = 0; i < n; i++) {
        if (isPalindrome(s.substring(i))) {
        
            // Return the number of
            // characters removed
            return i;
        }
    }
    
    // If no palindrome is found, remove
    // all but one character
    return n - 1;
}

const s = "abede";
const result = noOfAppends(s);
console.log(result);

Output
2

Using Knuth Morris Pratt Algorithm – O(n) Time and O(n) Space

The basic idea behind the approach is that we calculate the largest substring from the end 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.

The DFA (Deterministic Finite Automaton) mentioned in the context of the Knuth Morris Pratt Algorithm is a concept used to help find the longest prefix of a string that is also a suffix 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.

C++
// CPP program for the given approach 
// using 2D vector for DFA
#include <bits/stdc++.h>

using namespace std;

// Function to build the DFA and precompute the state
vector<vector<int>> buildDFA(string& s) {
    int n = s.length();
  
  	// Number of possible characters (ASCII range)
    int c = 256; 
  	
  	// Initialize 2D vector with zeros
    vector<vector<int>> dfa(n, vector<int>(c, 0)); 

    int x = 0;
    dfa[0][s[0]] = 1;

    // Build the DFA for the given string
    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]];
    }

    return dfa;
}

// Function to find the longest overlap
// between the string and its reverse
int longestOverlap(vector<vector<int>>& dfa, string& query) {
    int ql = query.length();
    int state = 0;

    // Traverse through the query to 
  	// find the longest overlap
    for (int i = 0; i < ql; i++) {
        state = dfa[state][query[i]];
    }
    return state;
}

// Function to find the minimum
// number of characters to append
int minAppends(string s) {
  
    // Reverse the string
    string reversedS = s;
    reverse(reversedS.begin(), reversedS.end());

    // Build the DFA for the reversed string
    vector<vector<int>> dfa = buildDFA(reversedS);

    // Get the longest overlap with the original string
    int longestOverlapLength = longestOverlap(dfa, s);

    // Minimum characters to append 
  	// to make the string a palindrome
    return s.length() - longestOverlapLength;
}

int main() {
    string s = "abede";
    cout << minAppends(s) << endl;
    return 0;
}
Java
// Java program for the given approach
// using 2D array for DFA
import java.util.*;

class GfG {

    // Function to build the DFA and precompute the state
    static int[][] buildDFA(String s) {
        int n = s.length();

        // Number of possible characters (ASCII range)
        int c = 256;

        // Initialize 2D array with zeros
        int[][] dfa = new int[n][c];

        int x = 0;
        dfa[0][s.charAt(0)] = 1;

        // Build the DFA for the given string
        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)];
        }

        return dfa;
    }

    // Function to find the longest overlap
    // between the string and its reverse
    static int longestOverlap(int[][] dfa, String query) {
        int ql = query.length();
        int state = 0;

        // Traverse through the query to 
        // find the longest overlap
        for (int i = 0; i < ql; i++) {
            state = dfa[state][query.charAt(i)];
        }
        return state;
    }

    // Function to find the minimum
    // number of characters to append
    static int minAppends(String s) {
      
        // Reverse the string
        String reversedS = new StringBuilder(s).reverse().toString();

        // Build the DFA for the reversed string
        int[][] dfa = buildDFA(reversedS);

        // Get the longest overlap with the original string
        int longestOverlapLength = longestOverlap(dfa, s);

        // Minimum characters to append 
        // to make the string a palindrome
        return s.length() - longestOverlapLength;
    }

     public static void main(String[] args) {
        String s = "abede";
        System.out.println(minAppends(s));
    }
}
Python
# Python program for the given approach 
# using 2D list for DFA

# Function to build the DFA and precompute the state
def buildDFA(s):
    n = len(s)

    # Number of possible characters (ASCII range)
    c = 256

    # Initialize 2D list with zeros
    dfa = [[0] * c for _ in range(n)]

    x = 0
    dfa[0][ord(s[0])] = 1

    # Build the DFA for the given string
    for i in range(1, n):
        for j in range(c):
            dfa[i][j] = dfa[x][j]
        dfa[i][ord(s[i])] = i + 1
        x = dfa[x][ord(s[i])]

    return dfa

# Function to find the longest overlap
# between the string and its reverse
def longestOverlap(dfa, query):
    ql = len(query)
    state = 0

    # Traverse through the query to 
    # find the longest overlap
    for i in range(ql):
        state = dfa[state][ord(query[i])]
    return state

# Function to find the minimum
# number of characters to append
def minAppends(s):
  
    # Reverse the string
    reversedS = s[::-1]

    # Build the DFA for the reversed string
    dfa = buildDFA(reversedS)

    # Get the longest overlap with the
    # original string
    longestOverlapLength = longestOverlap(dfa, s)

    # Minimum characters to append 
    # to make the string a palindrome
    return len(s) - longestOverlapLength

if __name__ == "__main__":
    s = "abede"
    print(minAppends(s))
C#
// C# program for the given approach
// using 2D array for DFA

using System;

class GfG {

    // Function to build the DFA and precompute the state
    static int[,] buildDFA(string s) {
        int n = s.Length;

        // Number of possible characters 
      	// (ASCII range)
        int c = 256;

        // Initialize 2D array with zeros
        int[,] dfa = new int[n, c];

        int x = 0;
        dfa[0, s[0]] = 1;

        // Build the DFA for the given string
        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]];
        }

        return dfa;
    }

    // Function to find the longest overlap
    // between the string and its reverse
    static int longestOverlap(int[,] dfa, string query) {
        int ql = query.Length;
        int state = 0;

        // Traverse through the query to 
        // find the longest overlap
        for (int i = 0; i < ql; i++) {
            state = dfa[state, query[i]];
        }
        return state;
    }

    // Function to find the minimum
    // number of characters to append
    static int minAppends(string s) {
      
        // Reverse the string using char array
        char[] reversedArray = s.ToCharArray();
        Array.Reverse(reversedArray);
        string reversedS = new string(reversedArray);

        // Build the DFA for the reversed string
        int[,] dfa = buildDFA(reversedS);

        // Get the longest overlap with the original string
        int longestOverlapLength = longestOverlap(dfa, s);

        // Minimum characters to append 
        // to make the string a palindrome
        return s.Length - longestOverlapLength;
    }

    static void Main() {
        string s = "abede";
        Console.WriteLine(minAppends(s));
    }
}
JavaScript
// JavaScript program for the given approach
// using 2D array for DFA

// Function to build the DFA and precompute the state
function buildDFA(s) {
    let n = s.length;

    // Number of possible characters
    // (ASCII range)
    let c = 256;

    // Initialize 2D array with zeros
    let dfa = Array.from({ length: n }, () => Array(c).fill(0));

    let x = 0;
    dfa[0][s.charCodeAt(0)] = 1;

    // Build the DFA for the given string
    for (let i = 1; i < n; i++) {
        for (let j = 0; j < c; j++) {
            dfa[i][j] = dfa[x][j];
        }
        dfa[i][s.charCodeAt(i)] = i + 1;
        x = dfa[x][s.charCodeAt(i)];
    }

    return dfa;
}

// Function to find the longest overlap
// between the string and its reverse
function longestOverlap(dfa, query) {
    let ql = query.length;
    let state = 0;

    // Traverse through the query to 
    // find the longest overlap
    for (let i = 0; i < ql; i++) {
        state = dfa[state][query.charCodeAt(i)];
    }
    return state;
}

// Function to find the minimum
// number of characters to append
function minAppends(s) {

    // Reverse the string
    let reversedS = s.split('').reverse().join('');

    // Build the DFA for the reversed string
    let dfa = buildDFA(reversedS);

    // Get the longest overlap with the original string
    let longestOverlapLength = longestOverlap(dfa, s);

    // Minimum characters to append 
    // to make the string a palindrome
    return s.length - longestOverlapLength;
}

let s = "abede";
console.log(minAppends(s));

Output
2

 Related Article : 



Next Article
Article Tags :
Practice Tags :

Similar Reads