Minimize removals to remove another string as a subsequence of a given string
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++
#include <bits/stdc++.h>
using namespace std;
void printMinimumRemovals(string str, string X)
{
int N = str.size();
int M = X.size();
int dp[N][M] = {};
for ( int j = 0; j < M; j++) {
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] == X[j]) {
dp[i][j] = dp[i - 1][j] + 1;
if (j != 0)
dp[i][j]
= min(dp[i][j], dp[i - 1][j - 1]);
}
else {
dp[i][j] = dp[i - 1][j];
}
}
}
cout << dp[N - 1][M - 1];
}
int main()
{
string str = "btagd" ;
string X = "bad" ;
printMinimumRemovals(str, X);
return 0;
}
|
Java
import java.io.*;
import java.lang.*;
import java.util.*;
class GFG {
static void printMinimumRemovals(String str, String X)
{
int N = str.length();
int M = X.length();
int dp[][] = new int [N][M];
for ( int j = 0 ; j < M; j++) {
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.charAt(i) == X.charAt(j)) {
dp[i][j] = dp[i - 1 ][j] + 1 ;
if (j != 0 )
dp[i][j] = Math.min(
dp[i][j], dp[i - 1 ][j - 1 ]);
}
else {
dp[i][j] = dp[i - 1 ][j];
}
}
}
System.out.println(dp[N - 1 ][M - 1 ]);
}
public static void main(String[] args)
{
String str = "btagd" ;
String X = "bad" ;
printMinimumRemovals(str, X);
}
}
|
Python3
def printMinimumRemovals(s, X):
N = len (s)
M = len (X)
dp = [[ 0 for x in range (M)] for y in range (N)]
for j in range (M):
if (s[ 0 ] = = X[j]):
dp[ 0 ][j] = 1
for i in range ( 1 , N):
for j in range (M):
if (s[i] = = X[j]):
dp[i][j] = dp[i - 1 ][j] + 1
if (j ! = 0 ):
dp[i][j] = min (dp[i][j], dp[i - 1 ][j - 1 ])
else :
dp[i][j] = dp[i - 1 ][j]
print (dp[N - 1 ][M - 1 ])
if __name__ = = "__main__" :
s = "btagd"
X = "bad"
printMinimumRemovals(s, X)
|
C#
using System;
public class GFG
{
static void printMinimumRemovals( string str, string X)
{
int N = str.Length;
int M = X.Length;
int [,] dp = new int [N, M];
for ( int j = 0; j < M; j++) {
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] == X[j]) {
dp[i, j] = dp[i - 1, j] + 1;
if (j != 0)
dp[i, j] = Math.Min(
dp[i, j], dp[i - 1, j - 1]);
}
else {
dp[i, j] = dp[i - 1, j];
}
}
}
Console.WriteLine(dp[N - 1, M - 1]);
}
public static void Main(String[] args)
{
string str = "btagd" ;
string X = "bad" ;
printMinimumRemovals(str, X);
}
}
|
Javascript
<script>
function printMinimumRemovals(str,X)
{
let N = str.length;
let M = X.length;
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;
}
}
for (let j = 0; j < M; j++) {
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] == X[j]) {
dp[i][j] = dp[i - 1][j] + 1;
if (j != 0)
dp[i][j] = Math.min(
dp[i][j], dp[i - 1][j - 1]);
}
else {
dp[i][j] = dp[i - 1][j];
}
}
}
document.write(dp[N - 1][M - 1]);
}
let str = "btagd" ;
let X = "bad" ;
printMinimumRemovals(str, X);
</script>
|
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++
#include <bits/stdc++.h>
using namespace std;
void printMinimumRemovals(string str, string X)
{
int N = str.size();
int M = X.size();
vector< int >curr(M+1 ,0);
vector< int >prev(M+1 ,0);
for ( int j = 0; j < M; j++) {
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] == X[j]) {
curr[j] = prev[j] + 1;
if (j != 0)
curr[j]
= min(curr[j], prev[j - 1]);
}
else {
curr[j] = prev[j];
}
}
prev = curr;
}
cout << curr[M - 1];
}
int main()
{
string str = "btagd" ;
string X = "bad" ;
printMinimumRemovals(str, X);
return 0;
}
|
Java
import java.util.Arrays;
public class Main {
public static void printMinimumRemovals(String str, String X) {
int N = str.length();
int M = X.length();
int [] curr = new int [M+ 1 ];
int [] prev = new int [M+ 1 ];
for ( int j = 0 ; j < M; j++) {
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.charAt(i) == X.charAt(j)) {
curr[j] = prev[j] + 1 ;
if (j != 0 )
curr[j] = Math.min(curr[j], prev[j - 1 ]);
}
else {
curr[j] = prev[j];
}
}
prev = Arrays.copyOf(curr, curr.length);
}
System.out.println(curr[M - 1 ]);
}
public static void main(String[] args) {
String str = "btagd" ;
String X = "bad" ;
printMinimumRemovals(str, X);
}
}
|
Python3
def printMinimumRemovals( str , X):
N = len ( str )
M = len (X)
curr = [ 0 ] * (M + 1 )
prev = [ 0 ] * (M + 1 )
for j in range (M):
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] = = X[j]:
curr[j] = prev[j] + 1
if j ! = 0 :
curr[j] = min (curr[j], prev[j - 1 ])
else :
curr[j] = prev[j]
prev = curr.copy()
print (curr[M - 1 ])
str = "btagd"
X = "bad"
printMinimumRemovals( str , X)
|
C#
using System;
using System.Collections.Generic;
class Program
{
static void PrintMinimumRemovals( string str, string X)
{
int N = str.Length;
int M = X.Length;
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);
}
for ( int j = 0; j < M; j++)
{
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] == X[j])
{
curr[j] = prev[j] + 1;
if (j != 0)
curr[j] = Math.Min(curr[j], prev[j - 1]);
}
else
{
curr[j] = prev[j];
}
}
prev = new List< int >(curr);
}
Console.WriteLine(curr[M - 1]);
}
static void Main( string [] args)
{
string str = "btagd" ;
string X = "bad" ;
PrintMinimumRemovals(str, X);
}
}
|
Javascript
function printMinimumRemovals(str, X) {
let N = str.length;
let M = X.length;
let curr = Array(M + 1).fill(0);
let prev = Array(M + 1).fill(0);
for (let j = 0; j < M; j++) {
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] === X[j]) {
curr[j] = prev[j] + 1;
if (j !== 0)
curr[j]
= Math.min(curr[j], prev[j - 1]);
}
else {
curr[j] = prev[j];
}
}
prev = [...curr];
}
console.log(curr[M - 1]);
}
let str = "btagd" ;
let X = "bad" ;
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
Share your thoughts in the comments
Please Login to comment...