Open In App

Minimum size substring to be removed to make a given string palindromic

Last Updated : 03 Apr, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

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>

Output
geeksfskeeg

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

Output
geeksrskeeg

Time Complexity: O(N), where N is the length of the given string.
Auxiliary Space: O(N)



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads