Minimum deletions to make String S the Subsequence of any String in the Set D
Last Updated :
14 Sep, 2023
Given a string S and a set of strings D, the task is to find the minimum number of deletions required to make the string S a subsequence of any string in the set D, such that the deletion can only be performed on the substring of S.
Examples:
Input: string S = "abcdefg", vector<string> D = {"abc", "defg", "ghi"}
Output: Minimum Deletion = 3
Explanation: This happens because the longest common subsequence is "defg" and its length is 4, and the length of the given string S is 7, so 7 - 4 = 3
Input: string S = "abcdefg", vector<string> D = {"abc", "defg", "ghi", "abcdefg"}
Output: Minimum Deletion = 0
Explanation: Since the string "abcdefg" is already present in the set of strings, the minimum number of deletions required will be 0, as no deletions need to be made to make S a subsequence of any string in the set D.
Input: string S = "abcdefg", vector<string> D = {"ty", "lk", "mp"}
Output: Minimum Deletion = 7
Explanation: This happens because there is no common subsequence in set of strings D.
Approach: It's important to note that this problem could be an NP-hard problem and can be solved following the below observations:
Observations:
- An efficient approach uses the concept of dynamic programming. One way to approach this is to use a 2D array, where the rows represent the characters of the string S and the columns represent the characters of the strings in set D.
- The value at each cell in the array represents the longest common subsequence between the substring of S up to that point and the string in the set D up to that point. If the current character in S and the current character in the string from the set D match, then the value at the current cell is the value at the cell above and to the left plus 1.
- If they do not match, then the value is the maximum of the value in the cell above and the value in the cell to the left.
- Once the 2D array is built, the minimum number of deletions required to make S a subsequence of any string in the set D is the length of S minus the maximum value in the array.
Follow the below steps to solve the problem:
- The first step is to define the function "minDeletions", which takes two arguments, "S" (the original string), and "D" (the set of strings).
- The function starts by declaring two variables, "n" and "m", which store the length of string S and D[i] respectively.
- The function then creates a 2D vector "dp" to store the length of the longest common subsequence (LCS) between S and D[i].
- The function uses nested for loops to iterate over the characters of S and D[i] and uses the dynamic programming approach to calculate the LCS.
- If the characters in S and D[i] are the same, the length of the LCS is incremented. If the characters are not the same, the length of the LCS is stored as the maximum between the two lengths stored in the previous cells of the dp vector.
- The function returns the minimum number of deletions required, which is equal to the length of S minus the length of the LCS.
- The main function starts by checking if the whole string S is present in the set of strings D. If it is, the output is 0, and the program exits.
- If S is not present in the set of strings D, the main function calculates the minimum number of deletions required for each string in the set and stores the result in the "mm" variable. The final result is the minimum of all these values.
- Finally, the output is printed, and the program ends.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
// Returns length of Longest
// Common Subsequence
int minDeletions(string S, string D)
{
int n = S.size();
int m = D.size();
// 2D array to store the length
// of the lCS
vector<vector<int> > dp(n + 1, vector<int>(m + 1, 0));
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (S[i - 1] == D[j - 1]) {
dp[i][j] = dp[i - 1][j - 1] + 1;
}
else {
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
}
}
}
// Returns minimum deletions required
return n - dp[n][m];
}
// Driver program to test above function
int main()
{
string S = "abcdefg";
vector<string> D = { "abc", "defg", "ghi" };
// Check if the whole string S is in
// set of strings D
for (string d : D) {
if (S == d) {
cout << 0 << endl;
exit(0);
}
}
int mm = S.size();
for (int i = 0; i < D.size(); i++) {
mm = min(mm, minDeletions(S, D[i]));
}
cout << mm << endl;
return 0;
}
Java
import java.util.Arrays;
class GFG {
static int minDeletions(String S, String D)
{
int n = S.length();
int m = D.length();
int dp[][] = new int[n + 1][m + 1];
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (S.charAt(i - 1) == D.charAt(j - 1)) {
dp[i][j] = dp[i - 1][j - 1] + 1;
}
else {
dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
}
}
}
return n - dp[n][m];
}
public static void main(String[] args)
{
String S = "abcdefg";
String D[] = { "abc", "defg", "ghi" };
for (String d : D) {
if (S.equals(d)) {
System.out.println(0);
System.exit(0);
}
}
int mm = S.length();
for (int i = 0; i < D.length; i++) {
mm = Math.min(mm, minDeletions(S, D[i]));
}
System.out.println(mm);
}
}
// This code is contributed by Susobhan Akhuli
Python
# Returns length of Longest Common Subsequence
def minDeletions(S, D):
n = len(S)
m = len(D)
# 2D array to store the length of the lCS
dp = [[0 for j in range(m + 1)] for i in range(n + 1)]
for i in range(1, n + 1):
for j in range(1, m + 1):
if S[i - 1] == D[j - 1]:
dp[i][j] = dp[i - 1][j - 1] + 1
else:
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1])
# Returns minimum deletions required
return n - dp[n][m]
if __name__ == '__main__':
S = "abcdefg"
D = ["abc", "defg", "ghi"]
for d in D:
if S == d:
print(0)
exit(0)
mm = len(S)
for i in range(len(D)):
mm = min(mm, minDeletions(S, D[i]))
print(mm)
# This code is contributed by Susobhan Akhuli
C#
using System;
using System.Collections.Generic;
namespace LCS {
class Program {
static int MinDeletions(string S, string D)
{
int n = S.Length;
int m = D.Length;
int[, ] dp = new int[n + 1, m + 1];
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (S[i - 1] == D[j - 1]) {
dp[i, j] = dp[i - 1, j - 1] + 1;
}
else {
dp[i, j] = Math.Max(dp[i - 1, j],
dp[i, j - 1]);
}
}
}
return n - dp[n, m];
}
static void Main(string[] args)
{
string S = "abcdefg";
List<string> D
= new List<string>{ "abc", "defg", "ghi" };
foreach(string d in D)
{
if (S == d) {
Console.WriteLine(0);
Environment.Exit(0);
}
}
int mm = S.Length;
for (int i = 0; i < D.Count; i++) {
mm = Math.Min(mm, MinDeletions(S, D[i]));
}
Console.WriteLine(mm);
}
}
}
// This code is contributed by Susobhan Akhuli
JavaScript
<script>
function minDeletions(S, D) {
let n = S.length;
let m = D.length;
// 2D array to store the length of the LCS
let dp = Array(n + 1)
.fill(0)
.map(() => Array(m + 1).fill(0));
for (let i = 1; i <= n; i++) {
for (let j = 1; j <= m; j++) {
if (S[i - 1] === D[j - 1]) {
dp[i][j] = dp[i - 1][j - 1] + 1;
} else {
dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
}
}
}
// Returns minimum deletions required
return n - dp[n][m];
}
// Driver program to test above function
let S = "abcdefg";
let D = ["abc", "defg", "ghi"];
for (let d of D) {
if (S === d) {
document.write(0);
process.exit(0);
}
}
let mm = S.length;
for (let i = 0; i < D.length; i++) {
mm = Math.min(mm, minDeletions(S, D[i]));
}
document.write(mm);
// This code is contributed by Susobhan Akhuli
</script>
Time Complexity: O(len(S)*len(D[i])*len(D))
Auxiliary Space: O(len(S)*len(D[i]))
Efficient approach: Space optimization
In the previous approach, the current value dp[i][j] is only depend upon the current and previous row values of DP. So to optimize the space complexity we use a single 1D array to store the computations.
Implementation steps:
- Create a 1D vector DP of size m+1.
- Set a base case by initializing the values of DP to 0.
- Now iterate over subproblems by the help of nested loop and get the current value from previous computations.
- Now initialize variables prev and curr used to store the previous and current value of Dp.
- After every iteration assign the value of curr to prev for further iteration.
- At last return final answer store in n - dp[m].
Implementation:
C++
#include <bits/stdc++.h>
using namespace std;
// Returns length of Longest
// Common Subsequence
int minDeletions(string S, string D)
{
int n = S.size();
int m = D.size();
// 1D array to store the length
// of the lCS
vector<int> dp(m + 1, 0);
for (int i = 1; i <= n; i++) {
int prev = 0;
for (int j = 1; j <= m; j++) {
int curr = dp[j];
if (S[i - 1] == D[j - 1]) {
dp[j] = prev + 1;
}
else {
dp[j] = max(dp[j - 1], dp[j]);
}
prev = curr;
}
}
// Returns minimum deletions required
return n - dp[m];
}
// Driver program to test above function
int main()
{
string S = "abcdefg";
vector<string> D = { "abc", "defg", "ghi" };
// Check if the whole string S is in
// set of strings D
for (string d : D) {
if (S == d) {
cout << 0 << endl;
exit(0);
}
}
int mm = S.size();
for (int i = 0; i < D.size(); i++) {
mm = min(mm, minDeletions(S, D[i]));
}
cout << mm << endl;
return 0;
}
// -- By bhardwajji
Java
import java.io.*;
import java.util.*;
public class Main {
public static int minDeletions(String S, String D) {
int n = S.length();
int m = D.length();
// 1D array to store the length
// of the LCS
int[] dp = new int[m + 1];
for (int i = 1; i <= n; i++) {
int prev = 0;
for (int j = 1; j <= m; j++) {
int curr = dp[j];
if (S.charAt(i - 1) == D.charAt(j - 1)) {
dp[j] = prev + 1;
} else {
dp[j] = Math.max(dp[j - 1], dp[j]);
}
prev = curr;
}
}
// Returns minimum deletions required
return n - dp[m];
}
// Driver program to test above function
public static void main(String[] args) {
String S = "abcdefg";
List<String> D = new ArrayList<>();
D.add("abc");
D.add("defg");
D.add("ghi");
// Check if the whole string S is in
// set of strings D
for (String d : D) {
if (S.equals(d)) {
System.out.println(0);
System.exit(0);
}
}
int mm = S.length();
for (String d : D) {
mm = Math.min(mm, minDeletions(S, d));
}
System.out.println(mm);
}
}
Python3
# Python program of the above approach
from typing import List
# Returns length of Longest
# Common Subsequence
def minDeletions(S: str, D: str) -> int:
n = len(S)
m = len(D)
# 1D array to store the length
# of the lCS
dp = [0] * (m + 1)
for i in range(1, n + 1):
prev = 0
for j in range(1, m + 1):
curr = dp[j]
if S[i - 1] == D[j - 1]:
dp[j] = prev + 1
else:
dp[j] = max(dp[j - 1], dp[j])
prev = curr
# Returns minimum deletions required
return n - dp[m]
# Driver program to test above function
if __name__ == "__main__":
S = "abcdefg"
D = ["abc", "defg", "ghi"]
# Check if the whole string S is in
# set of strings D
for d in D:
if S == d:
print(0)
exit(0)
mm = len(S)
for i in range(len(D)):
mm = min(mm, minDeletions(S, D[i]))
print(mm)
# This code is contributed by Susobhan Akhuli
C#
// C# code of the above approach
using System;
using System.Collections.Generic;
using System.Linq;
public class GFG {
// Returns length of Longest
// Common Subsequence
public static int MinDeletions(string S, string D)
{
int n = S.Length;
int m = D.Length;
// 1D array to store the length
// of the lCS
List<int> dp = Enumerable.Repeat(0, m + 1).ToList();
for (int i = 1; i <= n; i++) {
int prev = 0;
for (int j = 1; j <= m; j++) {
int curr = dp[j];
if (S[i - 1] == D[j - 1]) {
dp[j] = prev + 1;
}
else {
dp[j] = Math.Max(dp[j - 1], dp[j]);
}
prev = curr;
}
}
// Returns minimum deletions required
return n - dp[m];
}
// Driver program to test above function
public static void Main()
{
string S = "abcdefg";
List<string> D
= new List<string>() { "abc", "defg", "ghi" };
// Check if the whole string S is in
// set of strings D
foreach(string d in D)
{
if (S == d) {
Console.WriteLine(0);
Environment.Exit(0);
}
}
int mm = S.Length;
for (int i = 0; i < D.Count; i++) {
mm = Math.Min(mm, MinDeletions(S, D[i]));
}
Console.WriteLine(mm);
}
}
// This code is contributed by Susobhan Akhuli
JavaScript
// Returns length of Longest
// Common Subsequence
function minDeletions(S, D) {
let n = S.length;
let m = D.length;
// 1D array to store the length
// of the LCS
let dp = Array(m + 1).fill(0);
for (let i = 1; i <= n; i++) {
let prev = 0;
for (let j = 1; j <= m; j++) {
let curr = dp[j];
if (S[i - 1] === D[j - 1]) {
dp[j] = prev + 1;
} else {
dp[j] = Math.max(dp[j - 1], dp[j]);
}
prev = curr;
}
}
// Returns minimum deletions required
return n - dp[m];
}
// Driver program
let S = "abcdefg";
let D = ["abc", "defg", "ghi"];
// Check if the whole string S is in
// set of strings D
for (let d of D) {
if (S === d) {
console.log(0);
process.exit(0);
}
}
let mm = S.length;
for (let i = 0; i < D.length; i++) {
mm = Math.min(mm, minDeletions(S, D[i]));
}
console.log(mm);
// This code is contributed by Susobhan Akhuli
Time Complexity: O(n*m) , n is len(S) and m is len(D)
Auxiliary Space: O(m)
Similar Reads
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
Minimum cost to make a string free of a subsequence
Given string str consisting of lowercase English alphabets and an array of positive integer arr[] both of the same length. The task is to remove some characters from the given string such that no sub-sequence in the string forms the string "code". Cost of removing a character str[i] is arr[i]. Find
6 min read
Count the strings that are subsequence of the given string
Given a string S and an array arr[] of words, the task is to return the number of words from the array which is a subsequence of S. Examples: Input: S = âprogrammingâ, arr[] = {"prom", "amin", "proj"}Output: 2Explanation: "prom" and "amin" are subsequence of S while "proj" is not) Input: S = âgeeksf
11 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
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
Minimize operations to make string Z equal to T by appending subsequence of S
Given two strings S and T, and an empty string Z, the task is to print the minimum operations required to make string Z equal to T by appending any subsequence of S at the end of Z. If it is impossible to do so, then print -1. Example: Input: S = "aabce", T="ace" Output: 1 Input: S = "abacaba", T =
10 min read
Minimum changes required to make first string substring of second string
Given two strings S1 and S2 ( size of S1 <= Size of S2 ). The task is to find the minimum number of characters to be replaced in the string S2, such that the string S1 is a substring of S2. Examples: Input : S1 = cdef, S2 = abbdef Output : 1 Input : S1 = gfg, S2 = fgg Output : 2 Approach: Travers
8 min read
Count of Subsequences of given string X in between strings Y and Z
Given three strings, 'X', 'Y' and 'Z', the task is to count the number of subsequences of 'X' which is lexicographically greater than or equal to 'Y' and lexicographically lesser than or equal to 'Z'. Examples: Input: X = "abc", Y = "a", Z = "bc"Output: 6Explanation: The subsequences of X which are
15+ min read
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: 1Explanation:String "btag" has does n
14 min read
Split the string into minimum parts such that each part is in the another string
Given two strings A and B, the task is to split the string A into the minimum number of substrings such that each substring is in the string B. Note: If there is no way to split the string, then print -1 Examples: Input: A = "abcdab", B = "dabc" Output: 2 Explanation: The two substrings of A which i
11 min read