Open In App

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

Improve
Improve
Like Article
Like
Save
Share
Report

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 is impossible to make the new string equal to B by applying the given operations, then print -1.

Examples:

Input: A = “abc”, B = “abac”
Output: 2
Explanation:
Initially, C = “”. 
Step 1: Select subsequence “ab” from string A and append it to the empty string C, i.e. C = “ab”.
Step 2: Select subsequence “ac” from string A and append it to the end of string C, i.e. C = “abac”. 
Now, the string C is same as string B.
Therefore, count of operations required is 2.

Input: A = “geeksforgeeks”, B = “programming”
Output: -1

Approach: Follow the below steps to solve this problem:

  1. Initialize a Map to map characters present in the string A with their respective indices.
  2. For each character in string A, keep track of all of its occurrences.
  3. Initialize a variable, say ans, to store the count of operations required. As the number of operations must be greater than 1, set ans = 1.
  4. Iterate over the characters of string B and check if the character is present in the string A or not by using the Map.
  5. Lastly, maximize the length of the subsequence chosen from the string A for each operation.
  6. Finally, print the minimum operations required.

Below is the implementation of the above approach:

C++




// C++ program for the above approach
 
#include <bits/stdc++.h>
using namespace std;
 
// Function to count the minimum
// subsequences of a string A required
// to be appended to obtain the string B
void countminOpsToConstructAString(string A,   
                                   string B)
{
    // Size of the string
    int N = A.length();
 
    int i = 0;
 
    // Maps characters to their
    // respective indices
    map<char, set<int> > mp;
 
    // Insert indices of characters
    // into the sets
    for (i = 0; i < N; i++) {
        mp[A[i]].insert(i);
    }
 
    // Stores the position of the last
    // visited index in the string A.
    // Initially set it to -1.
    int previous = -1;
 
    // Stores the required count
    int ans = 1;
 
    // Iterate over the characters of B
    for (i = 0; i < B.length(); i++) {
        char ch = B[i];
 
        // If the character in B is
        // not present in A, return -1
        if (mp[ch].size() == 0) {
            cout << -1;
            return;
        }
 
        // Fetch the next index from B[i]'s set
        auto it = mp[ch].upper_bound(previous);
 
        // If the iterator points to
        // the end of that set
        if (it == mp[ch].end()) {
 
            previous = -1;
            ans++;
            --i;
            continue;
        }
 
        // If it doesn't point to the
        // end, update  previous
        previous = *it;
    }
 
    // Print the answer
    cout << ans;
}
 
// Driver Code
int main()
{
    string A = "abc", B = "abac";
    countminOpsToConstructAString(A, B);
 
    return 0;
}


Java




// Java program for the above approach
 
import java.util.*;
 
class GFG {
    // Function to count the minimum
    // subsequences of a string A required
    // to be appended to obtain the string B
    static void countminOpsToConstructAString(String A,
                                              String B)
    {
        // Size of the string
        int N = A.length();
 
        int i = 0;
 
        // Maps characters to their
        // respective indices
        Map<Character, TreeSet<Integer> > mp
            = new HashMap<>();
 
        // Insert indices of characters
        // into the sets
        for (i = 0; i < N; i++) {
            if (!mp.containsKey(A.charAt(i))) {
                mp.put(A.charAt(i), new TreeSet<Integer>());
            }
            mp.get(A.charAt(i)).add(i);
        }
 
        // Stores the position of the last
        // visited index in the string A.
        // Initially set it to -1.
        int previous = -1;
 
        // Stores the required count
        int ans = 1;
 
        // Iterate over the characters of B
        for (i = 0; i < B.length(); i++) {
            char ch = B.charAt(i);
 
            // If the character in B is
            // not present in A, return -1
            if (!mp.containsKey(ch)
                || mp.get(ch).size() == 0) {
                System.out.print("-1");
                return;
            }
 
            // Fetch the next index from B[i]'s set
            Integer it = mp.get(ch).higher(previous);
 
            // If the iterator points to
            // the end of that set
            if (it == null) {
 
                previous = -1;
                ans++;
                i--;
                continue;
            }
 
            // If it doesn't point to the
            // end, update previous
            previous = it;
        }
 
        // Print the answer
        System.out.print(ans);
    }
 
    // Driver Code
    public static void main(String[] args)
    {
        String A = "abc", B = "abac";
        countminOpsToConstructAString(A, B);
    }
}
 
// Contributed by adityashae15


Python3




# Python3 program for the above approach
from bisect import bisect_right
 
# Function to count the minimum
# subsequences of a A required
# to be appended to obtain the B
def countminOpsToConstructAString(A, B):
   
    # Size of the string
    N = len(A)
    i = 0
 
    # Maps characters to their
    # respective indices
    mp = [[] for i in range(26)]
 
    # Insert indices of characters
    # into the sets
    for i in range(N):
        mp[ord(A[i]) - ord('a')].append(i)
 
    # Stores the position of the last
    # visited index in the A.
    # Initially set it to -1.
    previous = -1
 
    # Stores the required count
    ans, i = 1, 0
 
    # Iterate over the characters of B
    while i < len(B):
        ch = B[i]
 
        # If the character in B is
        # not present in A, return -1
        if (len(mp[ord(ch) - ord('a')]) == 0):
            print(-1)
            return
 
        # Fetch the next index from B[i]'s set
        it = bisect_right(mp[ord(ch) - ord('a')], previous)
 
        # If the iterator points to
        # the end of that set
        if (it == len(mp[ord(ch) - ord('a')])):
            previous = -1
            ans += 1
            # i -= 1
            continue
 
        # If it doesn't point to the
        # end, update  previous
        previous = mp[ord(ch) - ord('a')][it]
        i += 1
 
    # Print answer
    print (ans)
 
# Driver Code
if __name__ == '__main__':
    A, B = "abc", "abac"
    countminOpsToConstructAString(A, B)
 
    # This code is contributed by mohit kumar 29.


C#




// C# program for the above approach
using System;
using System.Collections.Generic;
 
class GFG
{
   
    // Function to count the minimum
    // subsequences of a string A required
    // to be appended to obtain the string B
    static void CountminOpsToConstructAString(string A,
                                              string B)
    {
        // Size of the string
        int N = A.Length;
 
        int i = 0;
 
        // Maps characters to their
        // respective indices
        Dictionary<char, SortedSet<int> > mp
            = new Dictionary<char, SortedSet<int> >();
 
        // Insert indices of characters
        // into the sets
        for (i = 0; i < N; i++) {
            if (!mp.ContainsKey(A[i])) {
                mp.Add(A[i], new SortedSet<int>());
            }
            mp[A[i]].Add(i);
        }
 
        // Stores the position of the last
        // visited index in the string A.
        // Initially set it to -1.
        int previous = -1;
 
        // Stores the required count
        int ans = 1;
 
        // Iterate over the characters of B
        for (i = 0; i < B.Length; i++) {
            char ch = B[i];
 
            // If the character in B is
            // not present in A, return -1
            if (!mp.ContainsKey(ch) || mp[ch].Count == 0) {
                Console.Write("-1");
                return;
            }
 
            // Fetch the next index from B[i]'s set
            var view
                = mp[ch].GetViewBetween(previous + 1, N);
            if (view.Count == 0) {
                previous = -1;
                ans++;
                i--;
                continue;
            }
            int it = view.Min;
 
            // If it doesn't point to the
            // end, update previous
            previous = it;
        }
 
        // Print the answer
        Console.Write(ans);
    }
 
    // Driver Code
    public static void Main()
    {
        string A = "abc", B = "abac";
        CountminOpsToConstructAString(A, B);
    }
}
 
// This code is contributed by phasing17


Javascript




// JavaScript program for the above approach
function countminOpsToConstructAString(A, B) {
   
    // Size of the string
    const N = A.length;
    let i = 0;
 
    // Maps characters to their
    // respective indices
    const mp = new Array(26).fill(null).map(() => []);
 
    // Insert indices of characters
    // into the sets
    for (i = 0; i < N; i++) {
        mp[A.charCodeAt(i) - 'a'.charCodeAt(0)].push(i);
    }
 
    // Stores the position of the last
    // visited index in the A.
    // Initially set it to -1.
    let previous = -1;
 
    // Stores the required count
    let ans = 1;
    i = 0;
 
    // Iterate over the characters of B
    while (i < B.length) {
        const ch = B[i];
 
        // If the character in B is
        // not present in A, return -1
        if (mp[ch.charCodeAt(0) - 'a'.charCodeAt(0)].length == 0) {
            console.log(-1);
            return;
        }
 
        // Fetch the next index from B[i]'s set
        const it = mp[ch.charCodeAt(0) - 'a'.charCodeAt(0)].findIndex(idx => idx > previous);
 
        // If the iterator points to
        // the end of that set
        if (it == mp[ch.charCodeAt(0) - 'a'.charCodeAt(0)].length) {
            previous = -1;
            ans += 1;
            // i -= 1
            continue;
        }
 
        // If it doesn't point to the
        // end, update previous
        previous = mp[ch.charCodeAt(0) - 'a'.charCodeAt(0)][it];
        i += 1;
    }
 
    // Print answer
    console.log(ans);
}
 
// Driver Code
const A = "abc", B = "abac";
countminOpsToConstructAString(A, B);


Output: 

2

 

Time Complexity: O(N * logN)
Auxiliary Space: O(N) 



Last Updated : 11 Mar, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads