Minimize removals to remove another string as a subsequence of a given string
Last Updated :
10 Apr, 2023
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>
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
Similar Reads
Minimize length of a given string by removing subsequences forming valid parenthesis
Given a string S consisting of characters '(', ')', '[', ']', '{', '}', the task is to remove all balanced bracket subsequences from the string and print the remaining characters. Examples: Input: S = "((){()({})"Output: "({"Explanation: S[1] and S[2] forms a regular bracket sequence. Therefore, rem
11 min read
Rearrange a string S1 such that another given string S2 is not its subsequence
Given two strings S1 and S2 of size N and M respectively, the task is to rearrange characters in string S1 such that S2 is not a subsequence of it. If it is not possible to make such rearrangements, then print "-1". Otherwise, print the rearranged string S1. Examples: Input: S1 = "abcd", S2 = "ab"Ou
10 min read
Minimize length of a string by removing occurrences of another string from it as a substring
Given a string S and a string T, the task is to find the minimum possible length to which the string S can be reduced to after removing all possible occurrences of string T as a substring in string S. Examples: Input: S = "aabcbcbd", T = "abc"Output: 2Explanation:Removing the substring {S[1], ..., S
7 min read
Minimum cost to delete characters from String A to remove any subsequence as String B
Given two strings A and B of size N and M respectively, where B is a sub-sequence of A and an array arr[] of size N, where arr[i] is the cost to delete ith character from string A. The task is to find the minimum cost to delete characters from A such that after deletion no subsequence of A is the sa
15+ min read
Minimum subsequences of a string A required to be appended to obtain the string B
Given two strings A and B, the task is to count the minimum number of operations required to construct the string B by following operations: Select a subsequence of the string A.Append the subsequence at the newly formed string (initially empty). Print the minimum count of operations required. If it
8 min read
Check if a string can be converted to another given string by removal of a substring
Given two strings S and T of length N and M respectively, the task is to check if the string S can be converted to the string T by removing at most one substring of the string S. If found to be true, then print âYESâ. Otherwise, print âNOâ. Example: Input: S = âabcdefâ, T = âabcâ Output: YES Explana
7 min read
Maximum number of removals of given subsequence from a string
Given string str, the task is to count the maximum number of possible operations that can be performed on str. An operation consists of taking a sub-sequence 'gks' from the string and removing it from the string. Examples: Input: str = "ggkssk"Output: 1Explanation: After 1st operation: str = "gsk"No
6 min read
Minimum removal of subsequences of distinct consecutive characters required to empty a given string
Given a binary string, str, the task is to empty the given string by minimum number of removals of a single character or a subsequence containing distinct consecutive characters from str. Examples: Input: str = "0100100111" Output: 3 Explanation: Removing the subsequence "010101" from the string mod
6 min read
Make a given Binary String non-decreasing by removing the smallest subsequence
Given a binary string str of size N, the task is to find the length of the smallest subsequence such that after erasing the subsequence the resulting string will be the longest continuous non-decreasing string. Example : Input: str = "10011"Output: 1Explanation: Removal of the first occurrence of '1
8 min read
Minimize deletions in a Binary String to remove all subsequences of the form "0101"
Given a binary string S of length N, the task is to find the minimum number of characters required to be deleted from the string such that no subsequence of the form â0101â exists in the string. Examples: Input: S = "0101101"Output: 2Explanation: Removing S[1] and S[5] modifies the string to 00111.
6 min read