Minimum number of Appends needed to make a string palindrome (original) (raw)

Last Updated : 16 Nov, 2024

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 "abede
ba
" by adding **ba at the end of the string.

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

Table of Content

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 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);

`

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> 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>& 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));

`

**Related Article :