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 "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.
Table of Content
- Check palindrome every time - O(n^2) Time and O(n) Space
- Using Knuth Morris Pratt Algorithm - O(n) Time and O(n) Space
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 - 1if 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 dfaFunction 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 stateFunction 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) - longestOverlapLengthif 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 :