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++ 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 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. |
# 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# 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. |
<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++ 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 |
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);
}
} |
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)
|
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 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