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]
- If str[i] is equal to X[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> |
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
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!