Open In App

Minimize removals to remove another string as a subsequence of a given string

Improve
Improve
Like Article
Like
Save
Share
Report

Given two strings str and X of length N and M respectively, the task is to find the minimum characters required to be removed from the string str such that string str doesn’t contain the string X as a subsequence.

Examples:

Input: str = “btagd”, X = “bad”
Output: 1
Explanation:
String “btag” has does not contain “bad” as a subsequence. Therefore, only one removal is required.

Input: str = “bbaaddd”, X = “bad”
Output: 2

 

Approach: This problem can be solved by Dynamic Programming. Follow the steps below to solve the problem:

  • Traverse the string.
  • Initialize a 2D array dp[N][M], where N is the length of string str and M is the length of string X.
  • dp[i][j] represents the minimum number of character removal required in the substring str[0, i] such that there is no occurrence of substring X[0, j] as a subsequence.
  • The two transition states are:
    • If str[i] is equal to X[j],
      • Case 1: Remove the character str[i]
      • Case 2: Maintain the character str[i], by ensuring that there is no occurrence of X[0, j-1] as a subsequence in str[0, i]
      • Update dp[i][j] = min(dp[i − 1][j − 1], dp[i − 1][j] + 1)
    • If str[i] is not equal to X[j], str[i] can be kept as it is.
      •  Update dp[i][j] = dp[i – 1][j]
  • Print the minimum removals i.e, dp[N – 1][M – 1]

Below is the implementation of the above approach:

C++




// C++ implementation of
// the above approach
#include <bits/stdc++.h>
 
using namespace std;
 
// Function to print the minimum number of
// character removals required to remove X
// as a subsequence from the string str
void printMinimumRemovals(string str, string X)
{
 
    // Length of the string str
    int N = str.size();
 
    // Length of the string X
    int M = X.size();
 
    // Stores the dp states
    int dp[N][M] = {};
 
    // Fill first row of dp[][]
    for (int j = 0; j < M; j++) {
 
        // If X[j] matches with str[0]
        if (str[0] == X[j]) {
 
            dp[0][j] = 1;
        }
    }
 
    for (int i = 1; i < N; i++) {
 
        for (int j = 0; j < M; j++) {
 
            // If str[i] is equal to X[j]
            if (str[i] == X[j]) {
 
                // Update state after removing str[i[
                dp[i][j] = dp[i - 1][j] + 1;
 
                // Update state after keeping str[i]
                if (j != 0)
                    dp[i][j]
                        = min(dp[i][j], dp[i - 1][j - 1]);
            }
 
            // If str[i] is not equal to X[j]
            else {
 
                dp[i][j] = dp[i - 1][j];
            }
        }
    }
 
    // Print the minimum number
    // of characters removals
    cout << dp[N - 1][M - 1];
}
 
// Driver Code
int main()
{
    // Input
    string str = "btagd";
    string X = "bad";
 
    // Function call to get minimum
    // number of character removals
    printMinimumRemovals(str, X);
 
    return 0;
}


Java




// Java program for the above approach
import java.io.*;
import java.lang.*;
import java.util.*;
class GFG {
 
  // Function to print the minimum number of
  // character removals required to remove X
  // as a subsequence from the string str
  static void printMinimumRemovals(String str, String X)
  {
 
    // Length of the string str
    int N = str.length();
 
    // Length of the string X
    int M = X.length();
 
    // Stores the dp states
    int dp[][] = new int[N][M];
 
    // Fill first row of dp[][]
    for (int j = 0; j < M; j++) {
 
      // If X[j] matches with str[0]
      if (str.charAt(0) == X.charAt(j)) {
 
        dp[0][j] = 1;
      }
    }
 
    for (int i = 1; i < N; i++) {
 
      for (int j = 0; j < M; j++) {
 
        // If str[i] is equal to X[j]
        if (str.charAt(i) == X.charAt(j)) {
 
          // Update state after removing str[i[
          dp[i][j] = dp[i - 1][j] + 1;
 
          // Update state after keeping str[i]
          if (j != 0)
            dp[i][j] = Math.min(
            dp[i][j], dp[i - 1][j - 1]);
        }
 
        // If str[i] is not equal to X[j]
        else {
 
          dp[i][j] = dp[i - 1][j];
        }
      }
    }
 
    // Print the minimum number
    // of characters removals
    System.out.println(dp[N - 1][M - 1]);
  }
 
  // Driver code
  public static void main(String[] args)
  {
    // Input
    String str = "btagd";
    String X = "bad";
 
    // Function call to get minimum
    // number of character removals
    printMinimumRemovals(str, X);
  }
}
 
// This code is contributed by Kingash.


Python3




# Python 3 implementation of
# the above approach
 
# Function to print the minimum number of
# character removals required to remove X
# as a subsequence from the string str
def printMinimumRemovals(s, X):
 
    # Length of the string str
    N = len(s)
 
    # Length of the string X
    M = len(X)
 
    # Stores the dp states
    dp = [[0 for x in range(M)] for y in range(N)]
 
    # Fill first row of dp[][]
    for j in range(M):
       
        # If X[j] matches with str[0]
        if (s[0] == X[j]):
            dp[0][j] = 1
 
    for i in range(1, N):
        for j in range(M):
           
            # If s[i] is equal to X[j]
            if (s[i] == X[j]):
 
                # Update state after removing str[i[
                dp[i][j] = dp[i - 1][j] + 1
 
                # Update state after keeping str[i]
                if (j != 0):
                    dp[i][j] = min(dp[i][j], dp[i - 1][j - 1])
 
            # If str[i] is not equal to X[j]
            else:
                dp[i][j] = dp[i - 1][j]
 
    # Print the minimum number
    # of characters removals
    print(dp[N - 1][M - 1])
 
# Driver Code
if __name__ == "__main__":
 
    # Input
    s = "btagd"
    X = "bad"
 
    # Function call to get minimum
    # number of character removals
    printMinimumRemovals(s, X)
 
    # This code is contributed by ukasp.


C#




// C# program for above approach
using System;
public class GFG
{
 
  // Function to print the minimum number of
  // character removals required to remove X
  // as a subsequence from the string str
  static void printMinimumRemovals(string str, string X)
  {
 
    // Length of the string str
    int N = str.Length;
 
    // Length of the string X
    int M = X.Length;
 
    // Stores the dp states
    int[,] dp = new int[N, M];
 
    // Fill first row of dp[][]
    for (int j = 0; j < M; j++) {
 
      // If X[j] matches with str[0]
      if (str[0] == X[j]) {
 
        dp[0, j] = 1;
      }
    }
 
    for (int i = 1; i < N; i++) {
 
      for (int j = 0; j < M; j++) {
 
        // If str[i] is equal to X[j]
        if (str[i] == X[j]) {
 
          // Update state after removing str[i[
          dp[i, j] = dp[i - 1, j] + 1;
 
          // Update state after keeping str[i]
          if (j != 0)
            dp[i, j] = Math.Min(
            dp[i, j], dp[i - 1, j - 1]);
        }
 
        // If str[i] is not equal to X[j]
        else {
 
          dp[i, j] = dp[i - 1, j];
        }
      }
    }
 
    // Print the minimum number
    // of characters removals
    Console.WriteLine(dp[N - 1, M - 1]);
  }
 
// Driver code
public static void Main(String[] args)
{
   
    // Input
    string str = "btagd";
    string X = "bad";
 
    // Function call to get minimum
    // number of character removals
    printMinimumRemovals(str, X);
}
}
 
// This code is contributed by sanjoy_62.


Javascript




<script>
 
// Javascript program for the above approach
 
// Function to print the minimum number of
// character removals required to remove X
// as a subsequence from the string str
function printMinimumRemovals(str,X)
{
    // Length of the string str
    let N = str.length;
  
    // Length of the string X
    let M = X.length;
  
    // Stores the dp states
    let dp = new Array(N);
    for(let i=0;i<N;i++)
    {
        dp[i]=new Array(M);
        for(let j=0;j<M;j++)
        {
            dp[i][j]=0;
        }
         
    }
  
    // Fill first row of dp[][]
    for (let j = 0; j < M; j++) {
  
      // If X[j] matches with str[0]
      if (str[0] == X[j]) {
  
        dp[0][j] = 1;
      }
    }
  
    for (let i = 1; i < N; i++) {
  
      for (let j = 0; j < M; j++) {
  
        // If str[i] is equal to X[j]
        if (str[i] == X[j]) {
  
          // Update state after removing str[i[
          dp[i][j] = dp[i - 1][j] + 1;
  
          // Update state after keeping str[i]
          if (j != 0)
            dp[i][j] = Math.min(
            dp[i][j], dp[i - 1][j - 1]);
        }
  
        // If str[i] is not equal to X[j]
        else {
  
          dp[i][j] = dp[i - 1][j];
        }
      }
    }
  
    // Print the minimum number
    // of characters removals
    document.write(dp[N - 1][M - 1]);
}
 
 // Driver code
let str = "btagd";
let X = "bad";
// Function call to get minimum
// number of character removals
printMinimumRemovals(str, X);
 
 
// This code is contributed by avanitrachhadiya2155
</script>


Output: 

1

 

Time Complexity: O(N * M)
Auxiliary Space: O(N * M)

Efficient Approach : using array instead of 2d matrix to optimize space complexity

In previous code we can se that dp[i][j] is dependent upon dp[i+1][j-1] or dp[i][j-1] so we can assume that dp[i+1] is current row and dp[i] is previous row.

Implementations Steps :

  • It initializes two vectors curr and prev of length N+1 with all elements as 0.
  • Then it iterates over the length of the string str and X using nested loops.
  • If str[i] is equal to X[j], it updates the current state after removing str[i] and also the current state after keeping str[i] and removing X[j].
  • If str[i] is not equal to X[j], it updates the current state with the previous state value of the same index.
  • Finally, it prints the last element of the curr vector as the minimum number of character removals.

Implementation :

C++




// C++ implementation of the above approach
#include <bits/stdc++.h>
 
using namespace std;
 
// Function to print the minimum number of
// character removals required to remove X
// as a subsequence from the string str
void printMinimumRemovals(string str, string X)
{
 
    // Length of the string str
    int N = str.size();
 
    // Length of the string X
    int M = X.size();
 
    // Stores the rows dp states in 2 vectors
    vector<int>curr(M+1 ,0);
    vector<int>prev(M+1 ,0);
     
 
    // Fill first row of dp[][]
    for (int j = 0; j < M; j++) {
 
        // If X[j] matches with str[0]
        if (str[0] == X[j]) {
 
            curr[j] = 1;
            prev[j] = 1;
        }
    }
 
    for (int i = 1; i < N; i++) {
 
        for (int j = 0; j < M; j++) {
 
            // If str[i] is equal to X[j]
            if (str[i] == X[j]) {
 
                // Update state after removing str[i[
                curr[j] = prev[j] + 1;
 
                // Update state after keeping str[i]
                if (j != 0)
                    curr[j]
                        = min(curr[j], prev[j - 1]);
            }
 
            // If str[i] is not equal to X[j]
            else {
 
                curr[j] = prev[j];
            }
        }
        prev = curr;
    }
 
    // Print the minimum number
    // of characters removals
    cout << curr[M - 1];
}
 
// Driver Code
int main()
{
    // Input
    string str = "btagd";
    string X = "bad";
 
    // Function call to get minimum
    // number of character removals
    printMinimumRemovals(str, X);
 
    return 0;
}
 
// this code is contributed by bhardwajji


Java




import java.util.Arrays;
 
public class Main {
 
  // Function to print the minimum number of
  // character removals required to remove X
  // as a subsequence from the string str
  public static void printMinimumRemovals(String str, String X) {
 
    // Length of the string str
    int N = str.length();
 
    // Length of the string X
    int M = X.length();
 
    // Stores the rows dp states in 2 arrays
    int[] curr = new int[M+1];
    int[] prev = new int[M+1];
 
    // Fill first row of dp[][]
    for (int j = 0; j < M; j++) {
 
      // If X[j] matches with str[0]
      if (str.charAt(0) == X.charAt(j)) {
        curr[j] = 1;
        prev[j] = 1;
      }
    }
 
    for (int i = 1; i < N; i++) {
      for (int j = 0; j < M; j++) {
 
        // If str[i] is equal to X[j]
        if (str.charAt(i) == X.charAt(j)) {
 
          // Update state after removing str[i]
          curr[j] = prev[j] + 1;
 
          // Update state after keeping str[i]
          if (j != 0)
            curr[j] = Math.min(curr[j], prev[j - 1]);
        }
 
        // If str[i] is not equal to X[j]
        else {
          curr[j] = prev[j];
        }
      }
      prev = Arrays.copyOf(curr, curr.length); // Update the previous row with current row
    }
 
    // Print the minimum number
    // of characters removals
    System.out.println(curr[M - 1]);
  }
 
  // Driver Code
  public static void main(String[] args) {
 
    // Input
    String str = "btagd";
    String X = "bad";
 
    // Function call to get minimum
    // number of character removals
    printMinimumRemovals(str, X);
  }
}


Python3




def printMinimumRemovals(str, X):
    # Length of the string str
    N = len(str)
 
    # Length of the string X
    M = len(X)
 
    # Stores the rows dp states in 2 vectors
    curr = [0]*(M+1)
    prev = [0]*(M+1)
 
    # Fill first row of dp[][]
    for j in range(M):
 
        # If X[j] matches with str[0]
        if str[0] == X[j]:
            curr[j] = 1
            prev[j] = 1
 
    for i in range(1, N):
        for j in range(M):
 
            # If str[i] is equal to X[j]
            if str[i] == X[j]:
 
                # Update state after removing str[i[
                curr[j] = prev[j] + 1
 
                # Update state after keeping str[i]
                if j != 0:
                    curr[j] = min(curr[j], prev[j - 1])
 
            # If str[i] is not equal to X[j]
            else:
                curr[j] = prev[j]
 
        prev = curr.copy()
 
    # Print the minimum number
    # of characters removals
    print(curr[M - 1])
 
 
# Driver Code
str = "btagd"
X = "bad"
 
# Function call to get minimum
# number of character removals
printMinimumRemovals(str, X)


C#




using System;
using System.Collections.Generic;
 
class Program
{
  // Function to print the minimum number of
  // character removals required to remove X
  // as a subsequence from the string str
  static void PrintMinimumRemovals(string str, string X)
  {
    // Length of the string str
    int N = str.Length;
 
    // Length of the string X
    int M = X.Length;
 
    // Stores the rows dp states in 2 lists
    List<int> curr = new List<int>(M + 1);
    List<int> prev = new List<int>(M + 1);
 
    for (int i = 0; i < M + 1; i++)
    {
      curr.Add(0);
      prev.Add(0);
    }
 
    // Fill first row of dp[][]
    for (int j = 0; j < M; j++)
    {
      // If X[j] matches with str[0]
      if (str[0] == X[j])
      {
        curr[j] = 1;
        prev[j] = 1;
      }
    }
 
    for (int i = 1; i < N; i++)
    {
      for (int j = 0; j < M; j++)
      {
        // If str[i] is equal to X[j]
        if (str[i] == X[j])
        {
          // Update state after removing str[i[
          curr[j] = prev[j] + 1;
 
          // Update state after keeping str[i]
          if (j != 0)
            curr[j] = Math.Min(curr[j], prev[j - 1]);
        }
        // If str[i] is not equal to X[j]
        else
        {
          curr[j] = prev[j];
        }
      }
      prev = new List<int>(curr);
    }
 
    // Print the minimum number
    // of characters removals
    Console.WriteLine(curr[M - 1]);
  }
 
  // Driver Code
  static void Main(string[] args)
  {
    // Input
    string str = "btagd";
    string X = "bad";
 
    // Function call to get minimum
    // number of character removals
    PrintMinimumRemovals(str, X);
  }
}


Javascript




// JavaScript implementation of the above approach
 
function printMinimumRemovals(str, X) {
    // Length of the string str
let N = str.length;
 
// Length of the string X
let M = X.length;
 
// Stores the rows dp states in 2 arrays
let curr = Array(M + 1).fill(0);
let prev = Array(M + 1).fill(0);
 
// Fill first row of dp[][]
for (let j = 0; j < M; j++) {
 
    // If X[j] matches with str[0]
    if (str[0] === X[j]) {
 
        curr[j] = 1;
        prev[j] = 1;
    }
}
 
for (let i = 1; i < N; i++) {
 
    for (let j = 0; j < M; j++) {
 
        // If str[i] is equal to X[j]
        if (str[i] === X[j]) {
 
            // Update state after removing str[i[
            curr[j] = prev[j] + 1;
 
            // Update state after keeping str[i]
            if (j !== 0)
                curr[j]
                    = Math.min(curr[j], prev[j - 1]);
        }
 
        // If str[i] is not equal to X[j]
        else {
 
            curr[j] = prev[j];
        }
    }
    prev = [...curr];
}
 
// Print the minimum number
// of characters removals
console.log(curr[M - 1]);
}
 
// Driver Code
let str = "btagd";
let X = "bad";
 
// Function call to get minimum
// number of character removals
printMinimumRemovals(str, X);


Output:

1

Time Complexity : O(N*M), where N is the size of the first string and M is the size of the second string

Auxiliary Space: O(M), Space used for storing previous values



Last Updated : 10 Apr, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads