Minimum size substring to be removed to make a given string palindromic
Last Updated :
03 Apr, 2024
Given a string S, the task is to print the string after removing the minimum size substring such that S is a palindrome or not.
Examples:
Input: S = “pqrstsuvwrqp”
Output: pqrstsrqp
Explanation:
Removal of the substring “uvw” modifies S to a palindromic string.
Input: S = “geeksforskeeg”
Output: geeksfskeeg
Explanation:
Removal of substring “or” modifies S to a palindromic string.
Approach:
The idea is to include maximum size prefix and suffix from the given string S whose concatenation forms a palindrome. Then, choose the maximum length prefix or suffix from the remaining string which is a palindrome in itself.
Below is the illustration of the approach with the help of an image:
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
// Function to find palindromic
// prefix of maximum length
string palindromePrefix(string S)
{
int n = S.size();
// Finding palindromic prefix of
// maximum length
for (int i = n - 1; i >= 0; i--) {
string curr = S.substr(0, i + 1);
// Checking if curr substring
// is palindrome or not.
int l = 0, r = curr.size() - 1;
bool is_palindrome = 1;
while (l < r) {
if (curr[l] != curr[r]) {
is_palindrome = 0;
break;
}
l++;
r--;
}
// Condition to check if the
// prefix is a palindrome
if (is_palindrome)
return curr;
}
// if no palindrome exist
return "";
}
// Function to find the maximum size
// palindrome such that after removing
// minimum size substring
string maxPalindrome(string S)
{
int n = S.size();
if (n <= 1) {
return S;
}
string pre = "", suff = "";
// Finding prefix and suffix
// of same length
int i = 0, j = n - 1;
while (S[i] == S[j] && i < j) {
i++;
j--;
}
// Matching the ranges
i--;
j++;
pre = S.substr(0, i + 1);
suff = S.substr(j);
// It is possible that the whole
// string is palindrome.
// Case 1: Length is even and
// whole string is palindrome
if (j - i == 1) {
return pre + suff;
}
// Case 2: Length is odd and
// whole string is palindrome
if (j - i == 2) {
// Adding that mid character
string mid_char = S.substr(i + 1, 1);
return pre + mid_char + suff;
}
// Add prefix or suffix of the remaining
// string or suffix, whichever is longer
string rem_str
= S.substr(i + 1, j - i - 1);
string pre_of_rem_str
= palindromePrefix(rem_str);
// Reverse the remaining string to
// find the palindromic suffix
reverse(rem_str.begin(), rem_str.end());
string suff_of_rem_str
= palindromePrefix(rem_str);
if (pre_of_rem_str.size()
>= suff_of_rem_str.size()) {
return pre + pre_of_rem_str + suff;
}
else {
return pre + suff_of_rem_str + suff;
}
}
// Driver Code
int main()
{
string S = "geeksforskeeg";
cout << maxPalindrome(S);
return 0;
}
Java
// Java program of the
// above approach
import java.util.*;
class GFG{
// Function to find palindromic
// prefix of maximum length
static String palindromePrefix(String S)
{
int n = S.length();
// Finding palindromic prefix of
// maximum length
for(int i = n - 1; i >= 0; i--)
{
String curr = S.substring(0, i + 1);
// Checking if curr subString
// is palindrome or not.
int l = 0, r = curr.length() - 1;
boolean is_palindrome = true;
while (l < r)
{
if (curr.charAt(l) != curr.charAt(r))
{
is_palindrome = false;
break;
}
l++;
r--;
}
// Condition to check if the
// prefix is a palindrome
if (is_palindrome)
return curr;
}
// If no palindrome exist
return "";
}
// Function to find the maximum size
// palindrome such that after removing
// minimum size subString
static String maxPalindrome(String S)
{
int n = S.length();
if (n <= 1)
{
return S;
}
String pre = "", suff = "";
// Finding prefix and suffix
// of same length
int i = 0, j = n - 1;
while (S.charAt(i) ==
S.charAt(j) && i < j)
{
i++;
j--;
}
// Matching the ranges
i--;
j++;
pre = S.substring(0, i + 1);
suff = S.substring(j);
// It is possible that the whole
// String is palindrome.
// Case 1: Length is even and
// whole String is palindrome
if (j - i == 1)
{
return pre + suff;
}
// Case 2: Length is odd and
// whole String is palindrome
if (j - i == 2)
{
// Adding that mid character
String mid_char = S.substring(i + 1,
i + 2);
return pre + mid_char + suff;
}
// Add prefix or suffix of the remaining
// String or suffix, whichever is longer
String rem_str = S.substring(i + 1, j);
String pre_of_rem_str = palindromePrefix(rem_str);
// Reverse the remaining String to
// find the palindromic suffix
rem_str = reverse(rem_str);
String suff_of_rem_str = palindromePrefix(rem_str);
if (pre_of_rem_str.length() >=
suff_of_rem_str.length())
{
return pre + pre_of_rem_str + suff;
}
else
{
return pre + suff_of_rem_str + suff;
}
}
static String reverse(String input)
{
char[] a = input.toCharArray();
int l, r = a.length - 1;
for(l = 0; l < r; l++, r--)
{
char temp = a[l];
a[l] = a[r];
a[r] = temp;
}
return String.valueOf(a);
}
// Driver Code
public static void main(String[] args)
{
String S = "geeksforskeeg";
System.out.print(maxPalindrome(S));
}
}
// This code is contributed by Amit Katiyar
Python
# Python3 program of the
# above approach
# Function to find palindromic
# prefix of maximum length
def palindromePrefix(S):
n = len(S)
# Finding palindromic prefix
# of maximum length
for i in range(n - 1, -1, -1):
curr = S[0 : i + 1]
# Checking if curr substring
# is palindrome or not.
l = 0
r = len(curr) - 1
is_palindrome = 1
while (l < r):
if (curr[l] != curr[r]):
is_palindrome = 0
break
l += 1
r -= 1
# Condition to check if the
# prefix is a palindrome
if (is_palindrome):
return curr
# if no palindrome exist
return ""
# Function to find the maximum
# size palindrome such that
# after removing minimum size
# substring
def maxPalindrome(S):
n = len(S)
if (n <= 1):
return S
pre = ""
suff = ""
# Finding prefix and
# suffix of same length
i = 0
j = n - 1
while (S[i] == S[j] and
i < j):
i += 1
j -= 1
# Matching the ranges
i -= 1
j += 1
pre = S[0 : i + 1]
suff = S[j:]
# It is possible that the
# whole string is palindrome.
# Case 1: Length is even and
# whole string is palindrome
if (j - i == 1):
return pre + suff
# Case 2: Length is odd and
# whole string is palindrome
if (j - i == 2):
# Adding that mid character
mid_char = S[i + 1 : i + 2]
return pre + mid_char + suff
# Add prefix or suffix of the
# remaining string or suffix,
# whichever is longer
rem_str = S[i + 1 : j]
pre_of_rem_str = palindromePrefix(rem_str)
# Reverse the remaining string to
# find the palindromic suffix
list1 = list(rem_str)
list1.reverse()
rem_str = ''.join(list1)
suff_of_rem_str = palindromePrefix(rem_str)
if (len(pre_of_rem_str) >=
len(suff_of_rem_str)):
return (pre + pre_of_rem_str +
suff)
else:
return (pre + suff_of_rem_str +
suff)
# Driver Code
if __name__ == "__main__":
S = "geeksforskeeg"
print(maxPalindrome(S))
# This code is contributed by Chitranayal
C#
// C# program of the
// above approach
using System;
class GFG{
// Function to find palindromic
// prefix of maximum length
static String palindromePrefix(String S)
{
int n = S.Length;
// Finding palindromic prefix of
// maximum length
for(int i = n - 1; i >= 0; i--)
{
String curr = S.Substring(0, i + 1);
// Checking if curr subString
// is palindrome or not.
int l = 0, r = curr.Length - 1;
bool is_palindrome = true;
while (l < r)
{
if (curr[l] != curr[r])
{
is_palindrome = false;
break;
}
l++;
r--;
}
// Condition to check if the
// prefix is a palindrome
if (is_palindrome)
return curr;
}
// If no palindrome exist
return "";
}
// Function to find the maximum size
// palindrome such that after removing
// minimum size subString
static String maxPalindrome(String S)
{
int n = S.Length;
if (n <= 1)
{
return S;
}
String pre = "", suff = "";
// Finding prefix and suffix
// of same length
int i = 0, j = n - 1;
while (S[i] == S[j] && i < j)
{
i++;
j--;
}
// Matching the ranges
i--;
j++;
pre = S.Substring(0, i + 1);
suff = S.Substring(j);
// It is possible that the whole
// String is palindrome.
// Case 1: Length is even and
// whole String is palindrome
if (j - i == 1)
{
return pre + suff;
}
// Case 2: Length is odd and
// whole String is palindrome
if (j - i == 2)
{
// Adding that mid character
String mid_char = S.Substring(i + 1,
i + 2);
return pre + mid_char + suff;
}
// Add prefix or suffix of the remaining
// String or suffix, whichever is longer
String rem_str = S.Substring(i + 1, j);
String pre_of_rem_str = palindromePrefix(rem_str);
// Reverse the remaining String to
// find the palindromic suffix
rem_str = reverse(rem_str);
String suff_of_rem_str = palindromePrefix(rem_str);
if (pre_of_rem_str.Length >=
suff_of_rem_str.Length)
{
return pre + pre_of_rem_str + suff;
}
else
{
return pre + suff_of_rem_str + suff;
}
}
static String reverse(String input)
{
char[] a = input.ToCharArray();
int l, r = a.Length - 1;
for(l = 0; l < r; l++, r--)
{
char temp = a[l];
a[l] = a[r];
a[r] = temp;
}
return String.Join("", a);
}
// Driver Code
public static void Main(String[] args)
{
String S = "geeksforskeeg";
Console.Write(maxPalindrome(S));
}
}
// This code is contributed by shikhasingrajput
JavaScript
<script>
// javascript program for the
// above approach
// Function to find palindromic
// prefix of maximum length
function palindromePrefix(S)
{
let n = S.length;
// Finding palindromic prefix of
// maximum length
for(let i = n - 1; i >= 0; i--)
{
let curr = S.substr(0, i + 1);
// Checking if curr subString
// is palindrome or not.
let l = 0, r = curr.length - 1;
let is_palindrome = true;
while (l < r)
{
if (curr[l] != curr[r])
{
is_palindrome = false;
break;
}
l++;
r--;
}
// Condition to check if the
// prefix is a palindrome
if (is_palindrome)
return curr;
}
// If no palindrome exist
return "";
}
// Function to find the maximum size
// palindrome such that after removing
// minimum size subString
function maxPalindrome(S)
{
let n = S.length;
if (n <= 1)
{
return S;
}
let pre = "", suff = "";
// Finding prefix and suffix
// of same length
let i = 0, j = n - 1;
while (S[i] ==
S[j] && i < j)
{
i++;
j--;
}
// Matching the ranges
i--;
j++;
pre = S.substr(0, i + 1);
suff = S.substr(j);
// It is possible that the whole
// String is palindrome.
// Case 1: Length is even and
// whole String is palindrome
if (j - i == 1)
{
return pre + suff;
}
// Case 2: Length is odd and
// whole String is palindrome
if (j - i == 2)
{
// Adding that mid character
let mid_char = S.substr(i + 1,
i + 2);
return pre + mid_char + suff;
}
// Add prefix or suffix of the remaining
// String or suffix, whichever is longer
let rem_str = S.substr(i + 1, j);
let pre_of_rem_str = palindromePrefix(rem_str);
// Reverse the remaining String to
// find the palindromic suffix
rem_str = reverse(rem_str);
let suff_of_rem_str = palindromePrefix(rem_str);
if (pre_of_rem_str.length >=
suff_of_rem_str.length)
{
return pre + pre_of_rem_str + suff;
}
else
{
return pre + suff_of_rem_str + suff;
}
}
function reverse(input)
{
let a = input.split('');
let l, r = a.length - 1;
for(l = 0; l < r; l++, r--)
{
let temp = a[l];
a[l] = a[r];
a[r] = temp;
}
return parseInt(a);
}
// Driver Code
let S = "geeksforskeeg";
document.write(maxPalindrome(S));
// This code is contributed by avijitmondal1998.
</script>
Time Complexity: O(N2)Â
Auxiliary Space: O(N)
Minimum size substring to be removed to make a given string palindromic using Prefix Function
The idea is to choose the longest prefix and suffix such that they form a palindrome. After that from the remaining string we choose the longest prefix or suffix which is a palindrome. For computing the longest palindromic prefix(or suffix) we use Prefix Function which will take linear time to determine it.
Follow the steps to solve the above problem:
- Find the longest prefix(say s[0, l]) which is also a palindrome of the suffix(say s[n-l, n-1]) of the string str. Prefix and Suffix don’t overlap.
- Out of the remaining substring(s[l+1, n-l-1]), find the longest palindromic substring(say t) which is either a suffix or prefix of the remaining string.
- The concatenation of s[0, l], t and s[n-l, n-l-1] is the longest palindromic substring.
Below is the implementation of above approach:
C++
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
// Function to compute the optimized Prefix Function of a
// string in O(N) time
vector<ll> prefix_function(string s)
{
ll n = (ll)s.length();
vector<ll> pi(n);
for (ll i = 1; i < n; i++) {
ll j = pi[i - 1];
while (j > 0 && s[i] != s[j])
j = pi[j - 1];
if (s[i] == s[j])
j++;
pi[i] = j;
}
return pi;
}
// Function to find the length of the longest palindromic
// prefix (or suffix) using Prefix Function
ll LongestPalindromicPrefix(string str)
{
string temp = str + '?';
reverse(str.begin(), str.end());
temp += str;
ll n = temp.size();
vector<ll> lps = prefix_function(temp);
return lps[n - 1];
}
// Function to solve the problem and print the modified string
void solve(string s)
{
int n = s.size();
int i = 0, j = n - 1;
// Find the mismatched characters from the beginning and
// end of the string
while (i <= j) {
if (s[i] != s[j])
break;
i++, j--;
}
// If the entire string is a palindrome, no modification needed
if (i > j) {
cout << s << "\n";
return;
}
// Length of the common prefix and suffix
int l = i;
// Extract the substring between the mismatched characters
string t1, t2;
for (int z = i; z <= j; z++)
t1.push_back(s[z]);
// Create the reverse of the substring
t2 = t1;
reverse(t2.begin(), t2.end());
// Find the length of the longest palindromic prefix and suffix
int x = LongestPalindromicPrefix(t1);
int y = LongestPalindromicPrefix(t2);
// Print the modified string by removing the minimum size
// substring to make it palindromic
for (int i = 0; i < l; i++)
cout << s[i];
if (x > y)
for (int i = l; i < l + x; i++)
cout << s[i];
else
for (int i = (n - l) - y; i < (n - l); i++)
cout << s[i];
for (int i = (n - l); i < n; i++)
cout << s[i];
cout << "\n";
}
// Driver Code
int main()
{
string s = "geeksforskeeg";
solve(s);
return 0;
}
Java
import java.util.ArrayList;
import java.util.Collections;
public class Main {
// Function to compute the optimized Prefix Function of a
// string in O(N) time
static ArrayList<Long> prefixFunction(String s) {
int n = s.length();
ArrayList<Long> pi = new ArrayList<>(Collections.nCopies(n, 0L));
for (int i = 1; i < n; i++) {
long j = pi.get(i - 1);
while (j > 0 && s.charAt(i) != s.charAt((int) j))
j = pi.get((int) (j - 1));
if (s.charAt(i) == s.charAt((int) j))
j++;
pi.set(i, j);
}
return pi;
}
// Function to find the length of the longest palindromic
// prefix (or suffix) using Prefix Function
static long longestPalindromicPrefix(String str) {
String temp = str + '?';
StringBuilder reversedStr = new StringBuilder(str).reverse();
temp += reversedStr;
int n = temp.length();
ArrayList<Long> lps = prefixFunction(temp);
return lps.get(n - 1);
}
// Function to solve the problem and print the modified string
static void solve(String s) {
int n = s.length();
int i = 0, j = n - 1;
// Find the mismatched characters from the beginning and
// end of the string
while (i <= j) {
if (s.charAt(i) != s.charAt(j))
break;
i++;
j--;
}
// If the entire string is a palindrome, no modification needed
if (i > j) {
System.out.println(s);
return;
}
// Length of the common prefix and suffix
int l = i;
// Extract the substring between the mismatched characters
StringBuilder t1 = new StringBuilder();
for (int z = i; z <= j; z++)
t1.append(s.charAt(z));
// Create the reverse of the substring
StringBuilder t2 = new StringBuilder(t1).reverse();
// Find the length of the longest palindromic prefix and suffix
long x = longestPalindromicPrefix(t1.toString());
long y = longestPalindromicPrefix(t2.toString());
// Print the modified string by removing the minimum size
// substring to make it palindromic
for (int k = 0; k < l; k++)
System.out.print(s.charAt(k));
if (x > y)
for (int k = l; k < l + x; k++)
System.out.print(s.charAt(k));
else
for (int k = (n - l) - (int) y; k < (n - l); k++)
System.out.print(s.charAt(k));
for (int k = (n - l); k < n; k++)
System.out.print(s.charAt(k));
System.out.println();
}
// Driver Code
public static void main(String[] args) {
String s = "geeksforskeeg";
solve(s);
}
}
Python
import sys
def prefix_function(s):
"""
Function to compute the optimized Prefix Function of a string in O(N) time.
"""
n = len(s)
pi = [0] * n
j = 0
for i in range(1, n):
while j > 0 and s[i] != s[j]:
j = pi[j - 1]
if s[i] == s[j]:
j += 1
pi[i] = j
return pi
def longest_palindromic_prefix(s):
"""
Function to find the length of the longest palindromic prefix (or suffix) using Prefix Function.
"""
temp = s + '?'
reversed_str = s[::-1]
temp += reversed_str
n = len(temp)
lps = prefix_function(temp)
return lps[-1]
def solve(s):
"""
Function to solve the problem and print the modified string.
"""
n = len(s)
i, j = 0, n - 1
# Find the mismatched characters from the beginning and end of the string
while i <= j:
if s[i] != s[j]:
break
i += 1
j -= 1
# If the entire string is a palindrome, no modification needed
if i > j:
sys.stdout.write(s)
return
# Length of the common prefix and suffix
l = i
# Extract the substring between the mismatched characters
t1 = s[i:j + 1]
# Create the reverse of the substring
t2 = t1[::-1]
# Find the length of the longest palindromic prefix and suffix
x = longest_palindromic_prefix(t1)
y = longest_palindromic_prefix(t2)
# Print the modified string by removing the minimum size
# substring to make it palindromic
sys.stdout.write(s[:l])
if x > y:
sys.stdout.write(s[l:l + x])
else:
sys.stdout.write(s[n - l - y:n - l])
sys.stdout.write(s[n - l:] + '\n')
# Driver Code
if __name__ == "__main__":
s = "geeksforskeeg"
solve(s)
JavaScript
// Function to compute the optimized Prefix Function of a string in O(N) time
function prefixFunction(s) {
const n = s.length;
const pi = new Array(n).fill(0);
for (let i = 1; i < n; i++) {
let j = pi[i - 1];
while (j > 0 && s.charAt(i) !== s.charAt(j))
j = pi[j - 1];
if (s.charAt(i) === s.charAt(j))
j++;
pi[i] = j;
}
return pi;
}
// Function to find the length of the longest palindromic prefix (or suffix) using Prefix Function
function longestPalindromicPrefix(str) {
const temp = str + '?';
const reversedStr = str.split('').reverse().join('');
const tempReversed = temp + reversedStr;
const n = tempReversed.length;
const lps = prefixFunction(tempReversed);
return lps[n - 1];
}
// Function to solve the problem and print the modified string
function solve(s) {
const n = s.length;
let i = 0, j = n - 1;
// Find the mismatched characters from the beginning and end of the string
while (i <= j) {
if (s.charAt(i) !== s.charAt(j))
break;
i++;
j--;
}
// If the entire string is a palindrome, no modification needed
if (i > j) {
console.log(s);
return;
}
// Length of the common prefix and suffix
const l = i;
// Extract the substring between the mismatched characters
const t1 = s.substring(i, j + 1);
// Create the reverse of the substring
const t2 = t1.split('').reverse().join('');
// Find the length of the longest palindromic prefix and suffix
const x = longestPalindromicPrefix(t1);
const y = longestPalindromicPrefix(t2);
// Print the modified string by removing the minimum size substring to make it palindromic
let modifiedString = s.substring(0, l);
if (x > y)
modifiedString += s.substring(l, l + x);
else
modifiedString += s.substring(n - l - y, n - l);
modifiedString += s.substring(n - l);
console.log(modifiedString);
}
// Driver Code
const s = "geeksforskeeg";
solve(s);
Time Complexity:Â O(N), where N is the length of the given string.
Auxiliary Space:Â O(N)
Like Article
Suggest improvement
Share your thoughts in the comments
Please Login to comment...