Open In App

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

Last Updated : 11 Mar, 2023
Comments
Improve
Suggest changes
Like Article
Like
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) 


Next Article

Similar Reads