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;
int minDeletions(string S, string D)
{
int n = S.size();
int m = D.size();
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]);
}
}
}
return n - dp[n][m];
}
int main()
{
string S = "abcdefg" ;
vector<string> D = { "abc" , "defg" , "ghi" };
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);
}
}
|
Python
def minDeletions(S, D):
n = len (S)
m = len (D)
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 ])
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)
|
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);
}
}
}
|
Javascript
<script>
function minDeletions(S, D) {
let n = S.length;
let m = D.length;
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]);
}
}
}
return n - dp[n][m];
}
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);
</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;
int minDeletions(string S, string D)
{
int n = S.size();
int m = D.size();
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;
}
}
return n - dp[m];
}
int main()
{
string S = "abcdefg" ;
vector<string> D = { "abc" , "defg" , "ghi" };
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.io.*;
import java.util.*;
public class Main {
public static int minDeletions(String S, String D) {
int n = S.length();
int m = D.length();
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;
}
}
return n - dp[m];
}
public static void main(String[] args) {
String S = "abcdefg" ;
List<String> D = new ArrayList<>();
D.add( "abc" );
D.add( "defg" );
D.add( "ghi" );
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
from typing import List
def minDeletions(S: str , D: str ) - > int :
n = len (S)
m = len (D)
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
return n - dp[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)
|
C#
using System;
using System.Collections.Generic;
using System.Linq;
public class GFG {
public static int MinDeletions( string S, string D)
{
int n = S.Length;
int m = D.Length;
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;
}
}
return n - dp[m];
}
public static void Main()
{
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);
}
}
|
Javascript
function minDeletions(S, D) {
let n = S.length;
let m = D.length;
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;
}
}
return n - dp[m];
}
let S = "abcdefg" ;
let D = [ "abc" , "defg" , "ghi" ];
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);
|
Time Complexity: O(n*m) , n is len(S) and m is len(D)
Auxiliary Space: O(m)
Like Article
Suggest improvement
Share your thoughts in the comments
Please Login to comment...