Open In App

Minimum steps to delete a string after repeated deletion of palindrome substrings

Given a string containing characters as integers only. We need to delete all characters of this string in a minimum number of steps wherein in one step we can delete the substring which is a palindrome. After deleting a substring remaining parts are concatenated. 

Examples:



Input : s = “2553432”
Output : 2
We can delete all character of above string in
2 steps, first deleting the substring s[3, 5] “343”  
and then remaining string completely  s[0, 3] “2552”

Input : s = “1234”
Output : 4
We can delete all character of above string in 4 
steps only because each character need to be deleted 
separately. No substring of length 2 is a palindrome 
in above string.

Approach 1 : (Recursion + Memoization) :

We can use recursion to solve the problem and memoization to optimize it. If the size of the string is one then only one operation is needed. If the first two characters are the same then call on the subproblem with i+2 as an index and add 1 to the returned answer. And another case we have to handle is if the i-th character got found in the string from i+2 to end index, i.e. in between i+2 to end index if anywhere we find the same character then we should add up the answer of two subproblems, one is – starting index + 1, i-1 and i+1, ending index (here, i is the index where we got the starting index character again. 



Below is the implementation of the above approach:




//  C++ program to find minimum step to delete a string
#include <bits/stdc++.h>
using namespace std;
 
/* method returns minimum step for deleting the string,
   where in one step a palindrome is removed */
int helper(string str, int si, int ei,
           vector<vector<int> >& dp)
{
 
    // if the string is empty
    // need no operation
    if (si > ei)
        return 0;
 
    // string length one
    // need one operation
    if (ei - si + 1 == 1)
        return 1;
 
    // if already calculated
    if (dp[si][ei] != -1)
        return dp[si][ei];
 
    // to consider three options
    int op1 = 1e9, op2 = 1e9, op3 = 1e9;
 
    // delete first char and call
    // on the smaller subproblem
    op1 = 1 + helper(str, si + 1, ei, dp);
 
    // first two characters are same
    if (str[si] == str[si + 1])
        op2 = 1 + helper(str, si + 2, ei, dp);
 
    // found another index where the
    // character is same as si-th character
    for (int i = si + 2; i <= ei; i++) {
        if (str[si] == str[i])
            op3 = min(op3,
                      helper(str, si + 1, i - 1, dp)
                          + helper(str, i + 1, ei, dp));
    }
 
    // return the minimum b/w three options
    return dp[si][ei] = min({ op1, op2, op3 });
}
 
int minStepToDeleteString(string s)
{
    int n = s.size();
 
    // dp table to remove repeatations
    vector<vector<int> > dp(n, vector<int>(n, -1));
 
    // passing starting and ending index
    return helper(s, 0, n - 1, dp);
}
 
// Driver Code
int main()
{
    string str = "2553432";
    cout << minStepToDeleteString(str) << endl;
    return 0;
}
 
// this code is contributed by rajdeep999




// Java program to find minimum step to delete a string
import java.util.*;
 
public class Main {
    static int[][] dp;
    static int helper(char[] str, int si, int ei) {
        // if the string is empty
        // need no operation
        if (si > ei) {
            return 0;
        }
 
        // string length one
        // need one operation
        if (ei - si + 1 == 1) {
            return 1;
        }
 
        // if already calculated
        if (dp[si][ei] != -1) {
            return dp[si][ei];
        }
 
        // to consider three options
        int op1 = Integer.MAX_VALUE;
        int op2 = Integer.MAX_VALUE;
        int op3 = Integer.MAX_VALUE;
 
        // delete first char and call
        // on the smaller subproblem
        op1 = 1 + helper(str, si + 1, ei);
 
        // first two characters are same
        if (str[si] == str[si + 1]) {
            op2 = 1 + helper(str, si + 2, ei);
        }
 
        // found another index where the
        // character is same as si-th character
        for (int i = si + 2; i <= ei; i++) {
            if (str[si] == str[i]) {
                op3 = Math.min(op3, helper(str, si + 1, i - 1) + helper(str, i + 1, ei));
            }
        }
 
        // return the minimum between three options
        dp[si][ei] = Math.min(op1, Math.min(op2, op3));
        return dp[si][ei];
    }
 
    static int minStepToDeleteString(String s) {
        int n = s.length();
 
        // dp table to remove repetitions
        dp = new int[n][n];
        for (int i = 0; i < n; i++) {
            Arrays.fill(dp[i], -1);
        }
 
        // passing starting and ending index
        return helper(s.toCharArray(), 0, n - 1);
    }
 
    public static void main(String[] args) {
        String str = "2553432";
        System.out.println(minStepToDeleteString(str));
    }
}




#  Pythom program to find minimum step to delete a string
def helper(str, si, ei, dp):
    # if the string is empty
    # need no operation
    if si > ei:
        return 0
     
    # string length one
    # need one operation
    if ei - si + 1 == 1:
        return 1
     
    # if already calculated
    if dp[si][ei] != -1:
        return dp[si][ei]
 
    # to consider three options
    op1 = 1e9
    op2 = 1e9
    op3 = 1e9
 
    # delete first char and call
    # on the smaller subproblem
    op1 = 1 + helper(str, si + 1, ei, dp)
 
    # first two characters are same
    if str[si] == str[si + 1]:
        op2 = 1 + helper(str, si + 2, ei, dp)
 
    # found another index where the
    # character is same as si-th character
    for i in range(si+2, ei+1):
        if str[si] == str[i]:
            op3 = min(op3, helper(str, si + 1, i - 1, dp) + helper(str, i + 1, ei, dp))
 
    # return the minimum b/w three options
    dp[si][ei] = min(op1, op2, op3)
    return dp[si][ei]
 
def minStepToDeleteString(s:str) -> int:
    n = len(s)
 
    # dp table to remove repeatations
    dp = [[-1 for i in range(n)] for j in range(n)]
 
    # passing starting and ending index
    return helper(s, 0, n - 1, dp)
 
# Driver Code
if __name__ == "__main__":
    str = "2553432"
    print(minStepToDeleteString(str))
 
# This code is contributed by Potta Lokesh




//  Javascript program to find minimum step to delete a string
 
/* method returns minimum step for deleting the string,
   where in one step a palindrome is removed */
function helper( str, si, ei, dp)
{
 
    // if the string is empty
    // need no operation
    if (si > ei)
        return 0;
 
    // string length one
    // need one operation
    if (ei - si + 1 == 1)
        return 1;
 
    // if already calculated
    if (dp[si][ei] != -1)
        return dp[si][ei];
 
    // to consider three options
    let op1 = 1e9, op2 = 1e9, op3 = 1e9;
 
    // delete first char and call
    // on the smaller subproblem
    op1 = 1 + helper(str, si + 1, ei, dp);
 
    // first two characters are same
    if (str[si] == str[si + 1])
        op2 = 1 + helper(str, si + 2, ei, dp);
 
    // found another index where the
    // character is same as si-th character
    for (let i = si + 2; i <= ei; i++) {
        if (str[si] == str[i])
            op3 = Math.min(op3,
                      helper(str, si + 1, i - 1, dp)
                          + helper(str, i + 1, ei, dp));
    }
 
    // return the minimum b/w three options
    return dp[si][ei] = Math.min( op1, Math.min(op2, op3 ));
}
 
function minStepToDeleteString(s)
{
    let n = s.length;
 
    // dp table to remove repeatations
    let dp=new Array(n);
    for(let i=0; i<n; i++)
        dp[i]=new Array(n).fill(-1);
 
    // passing starting and ending index
    return helper(s, 0, n - 1, dp);
}
 
// Driver Code
let str = "2553432";
console.log(minStepToDeleteString(str));




//  C# program to find minimum step to delete a string
 
using System;
using System.Linq;
using System.Collections.Generic;
 
class GFG {
 
    /* method returns minimum step for deleting the string,
       where in one step a palindrome is removed */
    static int helper(string str, int si, int ei,int[,] dp)
    {
     
        // if the string is empty
        // need no operation
        if (si > ei)
            return 0;
     
        // string length one
        // need one operation
        if (ei - si + 1 == 1)
            return 1;
     
        // if already calculated
        if (dp[si,ei] != -1)
            return dp[si,ei];
     
        // to consider three options
        int op1 = 1000000000, op2 = 1000000000, op3 = 1000000000;
     
        // delete first char and call
        // on the smaller subproblem
        op1 = 1 + helper(str, si + 1, ei, dp);
     
        // first two characters are same
        if (str[si] == str[si + 1])
            op2 = 1 + helper(str, si + 2, ei, dp);
     
        // found another index where the
        // character is same as si-th character
        for (int i = si + 2; i <= ei; i++) {
            if (str[si] == str[i])
                op3 = Math.Min(op3,
                          helper(str, si + 1, i - 1, dp)
                              + helper(str, i + 1, ei, dp));
        }
     
        // return the minimum b/w three options
        return dp[si,ei] = Math.Min(op1, Math.Min(op2, op3 ));
    }
     
    static int minStepToDeleteString(string s)
    {
        int n = s.Length;
     
        // dp table to remove repeatations
        int [,] dp=new int[n,n];
        for(int i=0; i<n; i++)
        {
            for(int j=0; j<n; j++)
                dp[i,j]=-1;
        }
     
        // passing starting and ending index
        return helper(s, 0, n - 1, dp);
    }
     
    // Driver Code
    static public void Main()
    {
        string str = "2553432";
        Console.Write(minStepToDeleteString(str));
    }
}

Output
2

Time & Space complexity corrected by RainX (Abhijit Roy, NIT AGARTALA)

Time complexity: O(n3
Auxiliary Space: O(n3)

Approach 2 : (Dynamic Programming):

We can solve this problem using Dynamic programming. Let dp[i][j] denotes the number of steps it takes to delete the substring s[i, j]. Each character will be deleted alone or as part of some substring so in the first case we will delete the character itself and call subproblem (i+1, j). In the second case, we will iterate the overall occurrence of the current character on the right side, if K is the index of one such occurrence then the problem will reduce to two subproblems (i+1, K – 1) and (K+1, j). We can reach this subproblem (i+1, K-1) because we can just delete the same character and call for the mid-substring. We need to take care of a case when the first two characters are the same in that case we can directly reduce to the subproblem (i+2, j).
So after the above discussion of the relation among subproblems, we can write dp relation as follows, 

dp[i][j] = min(1 + dp[i+1][j],
          dp[i+1][K-1] + dp[K+1][j],  where s[i] == s[K]
          1 + dp[i+2][j] )

The total time complexity of the above solution is O(n^3) 




//  C++ program to find minimum step to delete a string
#include <bits/stdc++.h>
using namespace std;
 
/* method returns minimum step for deleting the string,
   where in one step a palindrome is removed */
int minStepToDeleteString(string str)
{
    int N = str.length();
 
    //  declare dp array and initialize it with 0s
    int dp[N + 1][N + 1];
    for (int i = 0; i <= N; i++)
        for (int j = 0; j <= N; j++)
            dp[i][j] = 0;
 
    // loop for substring length we are considering
    for (int len = 1; len <= N; len++)
    {
        // loop with two variables i and j, denoting
        // starting and ending of substrings
        for (int i = 0, j = len - 1; j < N; i++, j++)
        {
            // If substring length is 1, then 1 step
            // will be needed
            if (len == 1)
                dp[i][j] = 1;
            else
            {
                // delete the ith char individually
                // and assign result for subproblem (i+1,j)
                dp[i][j] = 1 + dp[i + 1][j];
 
                // if current and next char are same,
                // choose min from current and subproblem
                // (i+2,j)
                if (str[i] == str[i + 1])
                    dp[i][j] = min(1 + dp[i + 2][j], dp[i][j]);
 
                /*  loop over all right characters and suppose
                    Kth char is same as ith character then
                    choose minimum from current and two
                    substring after ignoring ith and Kth char */
                for (int K = i + 2; K <= j; K++)
                    if (str[i] == str[K])
                        dp[i][j] = min(dp[i+1][K-1] + dp[K+1][j],
                                                       dp[i][j]);
            }
        }
    }
 
    /* Uncomment below snippet to print actual dp tablex
    for (int i = 0; i < N; i++, cout << endl)
        for (int j = 0; j < N; j++)
            cout << dp[i][j] << " ";    */
 
    return dp[0][N - 1];
}
 
//  Driver code to test above methods
int main()
{
    string str = "2553432";
    cout << minStepToDeleteString(str) << endl;
    return 0;
}




// Java program to find minimum step to
// delete a string
public class GFG
{                           
    /* method returns minimum step for deleting
       the string, where in one step a
       palindrome is removed
     */
    static int minStepToDeleteString(String str) {
        int N = str.length();
 
        // declare dp array and initialize it with 0s
        int[][] dp = new int[N + 1][N + 1];
        for (int i = 0; i <= N; i++)
            for (int j = 0; j <= N; j++)
                dp[i][j] = 0;
 
        // loop for substring length we are considering
        for (int len = 1; len <= N; len++) {
             
            // loop with two variables i and j, denoting
            // starting and ending of substrings
            for (int i = 0, j = len - 1; j < N; i++, j++) {
     
                // If substring length is 1, then 1 step
                // will be needed
                if (len == 1)
                    dp[i][j] = 1;
                     
                else {
                    // delete the ith char individually
                    // and assign result for
                    // subproblem (i+1,j)
                    dp[i][j] = 1 + dp[i + 1][j];
 
                    // if current and next char are same,
                    // choose min from current and
                    // subproblem (i+2, j)
                    if (str.charAt(i) == str.charAt(i + 1))
                        dp[i][j] = Math.min(1 + dp[i + 2][j],
                                               dp[i][j]);
 
                    /* loop over all right characters and
                      suppose Kth char is same as ith
                      character then choose minimum from
                      current and two substring after
                      ignoring ith and Kth char
                     */
                    for (int K = i + 2; K <= j; K++)
                        if (str.charAt(i) == str.charAt(K))
                            dp[i][j] = Math.min(
                                         dp[i + 1][K - 1] +
                                        dp[K + 1][j], dp[i][j]);
                }
            }
        }
 
        /* Uncomment below snippet to print actual dp tablex
          
           for (int i = 0; i < N; i++){
           System.out.println();
           for (int j = 0; j < N; j++)
           System.out.print(dp[i][j] + " ");
           }
            */
             
        return dp[0][N - 1];
    }
 
    // Driver code to test above methods
    public static void main(String args[]) {
        String str = "2553432";
        System.out.println(minStepToDeleteString(str));
    }
}
// This code is contributed by Sumit Ghosh




# Python 3 program to find minimum
# step to delete a string
 
# method returns minimum step for
# deleting the string, where in one
# step a palindrome is removed
def minStepToDeleteString(str):
 
    N = len(str)
 
    # declare dp array and initialize
    # it with 0s
    dp = [[0 for x in range(N + 1)]
             for y in range(N + 1)]
 
    # loop for substring length
    # we are considering
    for l in range(1, N + 1):
         
        # loop with two variables i and j, denoting
        # starting and ending of substrings
        i = 0
        j = l - 1
        while j < N:
         
            # If substring length is 1,
            # then 1 step will be needed
            if (l == 1):
                dp[i][j] = 1
            else:
             
                # delete the ith char individually
                # and assign result for subproblem (i+1,j)
                dp[i][j] = 1 + dp[i + 1][j]
 
                # if current and next char are
                # same, choose min from current
                # and subproblem (i+2,j)
                if (str[i] == str[i + 1]):
                    dp[i][j] = min(1 + dp[i + 2][j], dp[i][j])
 
                ''' loop over all right characters and suppose
                    Kth char is same as ith character then
                    choose minimum from current and two
                    substring after ignoring ith and Kth char '''
                for K in range(i + 2, j + 1):
                    if (str[i] == str[K]):
                        dp[i][j] = min(dp[i + 1][K - 1] +
                                       dp[K + 1][j], dp[i][j])
                         
            i += 1
            j += 1
 
    # Uncomment below snippet to print
    # actual dp tablex
    # for (int i = 0; i < N; i++, cout << endl)
    # for (int j = 0; j < N; j++)
    #     cout << dp[i][j] << " ";
 
    return dp[0][N - 1]
 
# Driver Code
if __name__ == "__main__":
    str = "2553432"
    print( minStepToDeleteString(str))
 
# This code is contributed by ChitraNayal




// C# program to find minimum step to
// delete a string
using System;
 
class GFG {   
     
    /* method returns minimum step for deleting
    the string, where in one step a
    palindrome is removed */
    static int minStepToDeleteString(string str)
    {
        int N = str.Length;
 
        // declare dp array and initialize it
        // with 0s
        int [,]dp = new int[N + 1,N + 1];
         
        for (int i = 0; i <= N; i++)
            for (int j = 0; j <= N; j++)
                dp[i,j] = 0;
 
        // loop for substring length we are
        // considering
        for (int len = 1; len <= N; len++) {
             
            // loop with two variables i and j,
            // denoting starting and ending of
            // substrings
            for (int i = 0, j = len - 1; j < N; i++, j++)
            {
     
                // If substring length is 1, then 1
                // step will be needed
                if (len == 1)
                    dp[i,j] = 1;
                     
                else
                {
                    // delete the ith char individually
                    // and assign result for
                    // subproblem (i+1,j)
                    dp[i,j] = 1 + dp[i + 1,j];
 
                    // if current and next char are same,
                    // choose min from current and
                    // subproblem (i+2, j)
                    if (str[i] == str[i + 1])
                        dp[i,j] = Math.Min(1 + dp[i + 2,j],
                                                  dp[i,j]);
 
                    /* loop over all right characters and
                    suppose Kth char is same as ith
                    character then choose minimum from
                    current and two substring after
                    ignoring ith and Kth char
                    */
                    for (int K = i + 2; K <= j; K++)
                        if (str[i] == str[K])
                            dp[i,j] = Math.Min(
                                        dp[i + 1,K - 1] +
                                     dp[K + 1,j], dp[i,j]);
                }
            }
        }
 
        /* Uncomment below snippet to print actual dp tablex
         
        for (int i = 0; i < N; i++){
        System.out.println();
        for (int j = 0; j < N; j++)
        System.out.print(dp[i][j] + " ");
        } */
             
        return dp[0,N - 1];
    }
 
    // Driver code to test above methods
    public static void Main()
    {
        string str = "2553432";
        Console.Write(minStepToDeleteString(str));
    }
}
 
// This code is contributed by nitin mittal




<?php
// PHP program to find minimum step
// to delete a string
 
// method returns minimum step for
// deleting the string, where in one
// step a palindrome is removed */
function minStepToDeleteString($str)
{
    $N = strlen($str);
 
    // declare dp array and initialize
    // it with 0s
    $dp[$N + 1][$N + 1] = array(array());
    for ($i = 0; $i <= $N; $i++)
        for ($j = 0; $j <= $N; $j++)
            $dp[$i][$j] = 0;
 
    // loop for substring length we
    // are considering
    for ($len = 1; $len <= $N; $len++)
    {
        // loop with two variables i and j, denoting
        // starting and ending of substrings
        for ($i = 0, $j = $len - 1;
                     $j < $N; $i++, $j++)
        {
            // If substring length is 1, then
            // 1 step will be needed
            if ($len == 1)
                $dp[$i][$j] = 1;
            else
            {
                // delete the ith char individually
                // and assign result for subproblem (i+1,j)
                $dp[$i][$j] = 1 + $dp[$i + 1][$j];
 
                // if current and next char are same,
                // choose min from current and subproblem
                // (i+2,j)
                if ($str[$i] == $str[$i + 1])
                    $dp[$i][$j] = min(1 + $dp[$i + 2][$j],
                                          $dp[$i][$j]);
 
                /* loop over all right characters and suppose
                    Kth char is same as ith character then
                    choose minimum from current and two
                    substring after ignoring ith and Kth char */
                for ($K = $i + 2; $K <= $j; $K++)
                    if ($str[$i] == $str[$K])
                        $dp[$i][$j] = min($dp[$i + 1][$K - 1] +
                                          $dp[$K + 1][$j],
                                          $dp[$i][$j]);
            }
        }
    }
 
    /* Uncomment below snippet to print actual dp tablex
    for (int i = 0; i < N; i++, cout << endl)
        for (int j = 0; j < N; j++)
            cout << dp[i][j] << " "; */
 
    return $dp[0][$N - 1];
}
 
// Driver code
$str = "2553432";
echo minStepToDeleteString($str), "\n";
 
// This code is contributed by ajit.
?>




<script>
// Java Script program to find minimum step to
// delete a string
 
    /* method returns minimum step for deleting
       the string, where in one step a
       palindrome is removed
     */
    function minStepToDeleteString(str)
    {
        let N = str.length;
   
        // declare dp array and initialize it with 0s
        let dp = new Array(N + 1);
        for (let i = 0; i <= N; i++)
        {
            dp[i]=new Array(N+1);
            for (let j = 0; j <= N; j++)
                dp[i][j] = 0;
          }
        // loop for substring length we are considering
        for (let len = 1; len <= N; len++) {
               
            // loop with two variables i and j, denoting
            // starting and ending of substrings
            for (let i = 0, j = len - 1; j < N; i++, j++) {
       
                // If substring length is 1, then 1 step
                // will be needed
                if (len == 1)
                    dp[i][j] = 1;
                       
                else {
                    // delete the ith char individually
                    // and assign result for
                    // subproblem (i+1,j)
                    dp[i][j] = 1 + dp[i + 1][j];
   
                    // if current and next char are same,
                    // choose min from current and
                    // subproblem (i+2, j)
                    if (str[i] == str[i+1])
                        dp[i][j] = Math.min(1 + dp[i + 2][j],
                                               dp[i][j]);
   
                    /* loop over all right characters and
                      suppose Kth char is same as ith
                      character then choose minimum from
                      current and two substring after
                      ignoring ith and Kth char
                     */
                    for (let K = i + 2; K <= j; K++)
                        if (str[i] == str[K])
                            dp[i][j] = Math.min(
                                         dp[i + 1][K - 1] +
                                        dp[K + 1][j], dp[i][j]);
                }
            }
        }
   
        /* Uncomment below snippet to print actual dp tablex
            
           for (int i = 0; i < N; i++){
           System.out.println();
           for (int j = 0; j < N; j++)
           System.out.print(dp[i][j] + " ");
           }
            */
               
        return dp[0][N - 1];
    }
     
    // Driver code to test above methods
    let str = "2553432";
    document.write(minStepToDeleteString(str));
     
    // This code is contributed by avanitrachhadiya2155
</script>

Output
2

Time & Space complexity corrected by RainX (Abhijit Roy, NIT AGARTALA)

Time complexity : O(n3
Auxiliary Space : O(n3)


Article Tags :