Related Articles
Check if a string can be obtained by appending subsequences of another string
• Difficulty Level : Hard
• Last Updated : 04 Jan, 2021

Given two strings str1 and str2 of lengths N and M respectively, the task is to check if str2 can be formed by appending subsequences of str1 multiple times. If possible, print the minimum number of append operations required. Otherwise, print -1.

Examples:

Input: str1 = “abb”, str2 = “ababbbbb”
Output: 4
Explanation:
String str2 can be formed by appending subsequences of str1 = “ab” + “abb” + “bb” + “b” = “ababbbbb”. Since at least 4 operations are required, print 4.

Input: str1 = “mt”, str2 = “atttm”
Output: -1
Explanation:
Since ‘a’ is not present in the string str1, str2 cannot be generated from str1. Therefore, print -1.

Approach: The idea is to use the concept of Hashing based on the following observations below:

• Consider strings str1 = “abb” and str2 = “aba”. Find the position of character str2[0] in str1 whose index is greater than or equals to 0 i.e., index 0 of str1.
• Again, find str2[1] in str1 such that its index is greater than or equals to 1 i.e., index 1 of str1.
• Then, find str2[2] in str1 such that its index is greater than or equals to 2 which does not exist.
• Therefore, start again from index 0 and find str2[2] in str1 having an index greater than or equals to index 0 i.e., index 0 of str1.
• Hence, two subsequences “ab” and “a” can be appended to form “aba”.

Follow the below steps to solve the problem:

• Initialize an array of vectors vec[] of length 26.
• Push all the indices str1 having character ‘a’ in vec[0]. Similarly, push all indices having character ‘b’ in vec[1]. Do this for every character from ‘a’ to ‘z’.
• Initialize a variable result with 1 and position with 0 to store the minimum operations and current position of str1.
• Traverse the string str2 over the range [0, M] and for each character do the following:
• If vec[str2[i] – ‘a’] is empty then the character str2[i] is not present in str1. Hence, the answer is not possible. Therefore, print -1.
• Otherwise, find the lower bound of position in vec[str2[i] – ‘a’]. Let it be p. If p is equals the size of the vec[str2[i] – ‘a’] then increment the result by 1 and decrement i by 1 as answer for character str2[i] is not found yet and set position to 0.
• Otherwise, set position as (vec[p] + 1).
• After traversing, print the result as the minimum operations required.

Below is the implementation of the above approach:

C++

 `// C++ program for the above approach`   `#include `   `using` `namespace` `std;`   `// Function to find minimum operations` `// required to form str2 by adding` `// subsequences of str1` `void` `find(string str1, string str2)` `{`   `    ``// Initialize vector of length 26` `    ``vector<``int``> vec1[26];`   `    ``// Push indices of characters of str1` `    ``for` `(``int` `i = 0; i < str1.size(); i++)` `        ``vec1[str1[i] - ``'a'``].push_back(i);`   `    ``// Initialize the result & position` `    ``int` `result = 1, position = 0;`   `    ``// Traverse the string str2` `    ``for` `(``int` `i = 0; i < str2.size(); i++) ` `    ``{`   `        ``char` `c = str2[i];`   `        ``// Return if no answer exist` `        ``if` `(vec1.empty())` `        ``{` `            ``result = -1;` `            ``break``;` `        ``}`   `        ``// Pointer of vec1[c-'a']` `        ``vector<``int``>& vec2 = vec1;`   `        ``// Lower bound of position` `        ``int` `p = lower_bound(vec2.begin(),` `                            ``vec2.end(),` `                            ``position)` `                ``- vec2.begin();`   `        ``// If no index found` `        ``if` `(p == vec2.size())` `        ``{` `            ``// Increment result` `            ``result++;` `            ``i--;` `            ``position = 0;` `            ``continue``;` `        ``}`   `        ``// Update the position` `        ``else` `{` `            ``position = vec2[p] + 1;` `        ``}` `    ``}`   `    ``// Print the result` `    ``cout << result << ``'\n'``;` `}`   `// Driver Code` `int` `main()` `{` `    ``// Given string str1 & str2` `    ``string str1 = ``"abb"``, str2 = ``"ababbbbb"``;`   `    ``// Function Call` `    ``find(str1, str2);`   `    ``return` `0;` `}`

Java

 `// Java program for the above approach` `import` `java.io.*;` `import` `java.util.*;`   `class` `GFG {`   `    ``static` `void` `find(String str1, String str2)` `    ``{`   `        ``List > vec1` `            ``= ``new` `ArrayList >();`   `        ``// Initialize vector of length 26` `        ``for` `(``int` `i = ``0``; i < ``26``; i++) {` `            ``vec1.add(``new` `ArrayList());` `        ``}`   `        ``// Push indices of characters of str1` `        ``for` `(``int` `i = ``0``; i < str1.length(); i++)` `            ``vec1.get(str1.charAt(i) - ``'a'``).add(i);`   `        ``// Initialize the result & position` `        ``int` `result = ``1``, position = ``0``;`   `        ``// Traverse the string str2` `        ``for` `(``int` `i = ``0``; i < str2.length(); i++) ` `        ``{` `            ``char` `c = str2.charAt(i);`   `            ``// Return if no answer exist` `            ``if` `(vec1.get(c - ``'a'``).size() == ``0``) ` `            ``{` `                ``result = -``1``;` `                ``break``;` `            ``}`   `            ``List vec2 = vec1.get(c - ``'a'``);`   `            ``// Lower bound of position` `            ``int` `p = lower_bound(vec2, position);`   `            ``// If no index found` `            ``if` `(p == vec2.size())` `            ``{`   `                ``// Increment result` `                ``result++;` `                ``i--;` `                ``position = ``0``;` `                ``continue``;` `            ``}`   `            ``// Update the position` `            ``else` `{` `                ``position = vec2.get(p) + ``1``;` `            ``}` `        ``}`   `        ``// Print the result` `        ``System.out.println(result);` `    ``}`   `    ``// Driver Code` `    ``static` `int` `lower_bound(List vec2, ``int` `position)` `    ``{` `        ``int` `low = ``0``, high = vec2.size() - ``1``;`   `        ``while` `(low < high) {` `            ``int` `mid = (low + high) / ``2``;` `            ``if` `(vec2.get(mid) < position)` `                ``low = mid + ``1``;` `            ``else` `                ``high = mid;` `        ``}` `        ``return` `(vec2.get(low) < position) ? low + ``1` `: low;` `    ``}`   `    ``public` `static` `void` `main(String[] args)` `    ``{` `        ``// Given string str1 & str2` `        ``String str1 = ``"abb"``, str2 = ``"ababbbbb"``;`   `        ``// Function Call` `        ``find(str1, str2);` `    ``}` `}`

Python3

 `# Python3 program for the above approach` `from` `bisect ``import` `bisect_left`   `# Function to find minimum operations` `# required to form str2 by adding` `# subsequences of str1` `def` `find(str1, str2):` `  `  `    ``# Initialize vector of length 26` `    ``vec1 ``=` `[[] ``for` `i ``in` `range``(``26``)]`   `    ``# Push indices of characters of str1` `    ``for` `i ``in` `range``(``len``(str1)):` `        ``vec1[``ord``(str1[i]) ``-` `ord``(``'a'``)].append(i)`   `    ``# Initialize the result & position` `    ``result ``=` `1` `    ``position ``=` `0`   `    ``# Traverse the str2` `    ``i ``=` `0` `    ``while` `i < ``len``(str2):` `        ``c ``=` `str2[i]`   `        ``# Return if no answer exist` `        ``if` `(``len``(vec1[``ord``(c) ``-` `ord``(``'a'``)]) ``=``=` `0``):` `            ``result ``=` `-``1` `            ``break`   `        ``# Pointer of vec1[c-'a']` `        ``vec2 ``=` `vec1[``ord``(c) ``-` `ord``(``'a'``)]`   `        ``# Lower bound of position` `        ``p ``=` `bisect_left(vec2, position)` `        `  `        ``#print(c)`   `        ``# If no index found` `        ``if` `(p ``=``=` `len``(vec2)):`   `            ``# Increment result` `            ``result ``+``=` `1` `            `  `            ``#i-=1` `            ``position ``=` `0` `            ``continue` `            `  `        ``# Update the position` `        ``else``:` `            ``i ``+``=` `1` `            ``position ``=` `vec2[p] ``+` `1`   `    ``# Print the result` `    ``print``(result)`   `# Driver Code` `if` `__name__ ``=``=` `'__main__'``:` `  `  `    ``# Given str1 & str2` `    ``str1 ``=` `"abb"` `    ``str2 ``=` `"ababbbbb"`   `    ``# Function Call` `    ``find(str1, str2)`   `# 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 find minimum operations` `// required to form str2 by adding` `// subsequences of str1    ` `static` `void` `find(``string` `str1, ``string` `str2)` `{` `    ``List> vec1 = ``new` `List>();` `    `  `    ``// Initialize vector of length 26` `    ``for``(``int` `i = 0; i < 26; i++)` `    ``{` `        ``vec1.Add(``new` `List<``int``>());` `    ``}` `    `  `    ``// Push indices of characters of str1` `    ``for``(``int` `i = 0; i < str1.Length; i++)` `    ``{` `        ``vec1[str1[i] - ``'a'``].Add(i);` `    ``}` `    `  `    ``// Initialize the result & position` `    ``int` `result = 1, position = 0;` `    `  `    ``// Traverse the string str2` `    ``for``(``int` `i = 0; i < str2.Length; i++)` `    ``{` `        ``char` `c = str2[i];` `        `  `        ``// Return if no answer exist` `        ``if` `(vec1.Count == 0)` `        ``{` `            ``result = -1;` `            ``break``;` `        ``}` `        ``List<``int``> vec2 = vec1;` `        `  `        ``// Lower bound of position` `        ``int` `p = lower_bound(vec2, position);` `        `  `        ``// If no index found` `        ``if` `(p == vec2.Count)` `        ``{` `            `  `            ``// Increment result` `            ``result++;` `            ``i--;` `            ``position = 0;` `            ``continue``;` `        ``}` `        `  `        ``// Update the position` `        ``else` `        ``{` `            ``position = vec2[p] + 1;` `        ``}` `    ``}` `    `  `    ``// Print the result` `    ``Console.WriteLine(result);` `}`   `static` `int` `lower_bound(List<``int``> vec2,` `                       ``int` `position)` `{` `    ``int` `low = 0, high = vec2.Count - 1;` `    `  `    ``while` `(low < high)` `    ``{` `        ``int` `mid = (low + high) / 2;` `        `  `        ``if` `(vec2[mid] < position)` `        ``{` `            ``low = mid + 1;` `        ``}` `        ``else` `        ``{` `            ``high = mid;` `        ``}` `    ``}` `    ``return` `(vec2[low] < position) ?` `                  ``low + 1 : low;` `}`   `// Driver Code` `static` `public` `void` `Main()` `{` `    `  `    ``// Given string str1 & str2` `    ``string` `str1 = ``"abb"``, str2 = ``"ababbbbb"``;` `    `  `    ``// Function Call` `    ``find(str1, str2);` `}` `}`   `// This code is contributed by avanitrachhadiya2155`

Output

`4`

Time Complexity: O(N + M log N)
Auxiliary Space: O(M + N)

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.

My Personal Notes arrow_drop_up
Recommended Articles
Page :