Minimum subsequences of a string A required to be appended to obtain the string B


In this problem, we need to construct the str2 by using the subsequences of the str1. To solve the problem, we can find subsequences of the str1 so that it can cover the substring with a maximum length of str2. Here, we will learn two different approaches to solving the problem.

Problem statement â€“ We have given two strings, str1, and str2, of different lengths. We need to construct the str2 from the str1 by following the condition below.

  • Pick any subsequence from the str1, and append it to the new string, which is empty initially.

We need to return the minimum number of operations require to construct the str2 or print -1 if it is not possible to construct str2.

Sample examples

Input â€“ str1 = "acd", str2 = "adc"

Output– 2

Explanation

  • The first subsequence from str1 is ‘ad’. So, our string can be ‘ad’.

  • After that, we can take the ‘c’ subsequence from str1 and append it to ‘ad’ to make it ‘adc.’

Input– str1 = "adcb", str2 = "abdca"

Output– 3

Explanation

  • The first subsequence is ‘ab’ from str1.

  • After that, we can take the ‘dc’ string, and the resultant string will be ‘abdc'

  • Next, we can take the ‘a’ subsequence to make the final string ‘abdca’.

Approach 1

In this approach, we will iterate str1 to find the multiple subsequences and append it to the resultant string.

Algorithm

  • Define the ‘arr’ array of length 26 and initialize all elements with 0 to store the character's presence in str1.

  • Iterate through the str1, and update the value of array elements according to the ASCII value of characters

  • Define the ‘last’ variable and initialize with -1 to track the last visited element. Also, define the ‘cnt’ variable and initialize it with 0 to store the count of operations.

  • Start traversing the str2 using the loop.

  • If the current character is not present in str1, return -1.

  • Initialize the ‘j’ variable with the ‘last + 1’ value.

  • Use the while loop to make iterations until the value of the ‘j’ is less than len, and str1[j] is not equal to the character

  • If the value of the ‘j’ is greater than ‘len’, we traverse the ‘str1’. Increase the value of the ‘cnt’ variable, initialize ‘last’ with -1 as we need to traverse ‘str1’ again, decrease the value of ‘I’ by 1, as we need to consider the current character again, use the ‘continue’ keyword to continue the iteration.

  • Update the value of the ‘last’ variable by ‘j’.

  • Return ‘cnt + 1’ once all iterations of the loop are complete. Here, we need to add ‘1’ to ‘cnt’ as we are not considering the last operation.

Example

#include <iostream>
using namespace std;

// function to count the minimum number of operations required to get string str2 from subsequences of string str1.
int minOperations(string str1, string str2){
   int len = str1.length();
   // creating an array of size 26 to store the presence of characters in string str1.
   int arr[26] = {0};
   // storing the presence of characters in string str1.
   for (int i = 0; i < len; i++){
      arr[str1[i] - 'a']++;
   }
   // store the last iterated index of string str1.
   int last = -1;
   //  to store the count of operations.
   int cnt = 0;
   for (int i = 0; i < str2.length(); i++){
      char ch = str2[i];
      // if the character is not present in string str1, then return -1.
      if (arr[ch - 'a'] == 0){
         return -1;
      }
      // start iterating from the jth index of string str1 to find the character ch.
      int j = last + 1;
      while (j < len && str1[j] != ch){
          j++;
      }
      // if j is equal to the length of string str1, then increment the count, set last to -1, and decrement i.
      if (j >= len){
         cnt++;
         last = -1;
         --i;
         continue;
      }
      // set last to j.
      last = j;
   }
   // return cnt + 1 as we haven't counted the last operation.
   return cnt + 1;
}
int main(){
   string str1 = "acd", str2 = "adc";
   int operations = minOperations(str1, str2);
   cout << "Minimum number of operations required to create string B from the subsequences of the string A is: " << operations << "\n";
   return 0;
}

Output

Minimum number of operations required to create string B from the subsequences of the string A is: 2

Time complexity – O(N*M), Where N is the length of str2, and M is the length of str1.

Space complexity – O(1), as we don’t use any dynamic space.

Approach 2

In this approach, we will use the map and set data structure to make the above approach efficient. The logic to solve the problem will be the same as above approach.

Algorithm

  • Define the ‘chars_mp’ to store the char -> set{} as a key-value pair.

  • In the map, store the set of indexes where a particular character is present in the str1 string

  • Define the ‘last’ and ‘cnt’ variables

  • Start traversing the str2. If the size of the set containing indexes of the current character is zero, return -1.

  • Find the upper bound of the ‘last’ in the set of indexes of the current character.

  • If the upper bound is not found, increase the value of ‘cnt’ by 1, set ‘last’ to -1, decrease the value of ‘I’ by 1, and use the continue keyword.

  • Update the value of the ‘last’ variable.

  • When the loop iteration completes, return the value of the ‘cnt’ variable

Example

#include <iostream>
#include <map> 
#include <set>
using namespace std;

// function to count the minimum number of operations required to get string str2 from subsequences of string str1.
int minOperations(string str1, string str2){
   // Length of string str1
   int len = str1.length();
   // creating the map to store the set of indices for each character in str1
   map<char, set<int>> chars_mp;
   // Iterate over the characters of str1 and store the indices of each character in the map
   for (int i = 0; i < len; i++){
      chars_mp[str1[i]].insert(i);
   }
   // store the last visited index of str1
   int last = -1;
   // Stores the required count
   int cnt = 1;
   // Iterate over the characters of str2
   for (int i = 0; i < str2.length(); i++){
      char ch = str2[i];
      // If the set of indices of str2[i] is empty, then return -1
      if (chars_mp[ch].size() == 0){
         return -1;
      }
      // If the set of indices of str2[i] is not empty, then find the upper bound of last in the set of indices of str2[i]
      // It finds the smallest index of str2[i] which is greater than last
      auto it = chars_mp[ch].upper_bound(last);
      // If the upper bound is equal to the end of the set, then increment the count and update last to -1
       if (it == chars_mp[ch].end()){
          last = -1;
          cnt++;
          // Decrement I by 1 to process the current character again
          --i;
          continue;
      }
      // Update last to the current index
      last = *it;
   }
   return cnt;
}
int main(){
   string str1 = "adcb", str2 = "abdca";
   int operations = minOperations(str1, str2);
   cout << "Minimum number of operations required to create string B from the subsequences of the string A is: " << operations << "\n";
   return 0;
}

Output

Minimum number of operations required to create string B from the subsequences of the string A is: 3

Time complexity – O(N*logN), as we traverse the str2 and find the upper bound of the ‘last’ index in the loop.

Space complexity – O(N), as we use the map to store indexes of characters.

Updated on: 10-Aug-2023

100 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements