Count the strings that are subsequence of the given string
Given a string S and an array arr[] of words, the task is to return the number of words from the array which is a subsequence of S.
Examples:
Input: S = “programming”, arr[] = {“prom”, “amin”, “proj”}
Output: 2
Explanation: “prom” and “amin” are subsequence of S while “proj” is not)Input: S = “geeksforgeeks”, arr[] = {“gfg”, “geek”, “geekofgeeks”, “for”}
Output: 3
Explanation:” gfg”, “geek” and “for” are subsequences of S while “geekofgeeks” is not.
Naive Approach: The basic way to solve the problem is as follows:
The idea is to check all strings in the words array arr[] which are subsequences of S by recursion.
Below is the implementation of the above approach:
C++
// C++ code for the above approach: #include <bits/stdc++.h> using namespace std; bool isSubsequence(string& str1, int m, string& str2, int n) { if (m == 0) return true ; if (n == 0) return false ; // If last characters of two strings // are matching if (str1[m - 1] == str2[n - 1]) return isSubsequence(str1, m - 1, str2, n - 1); // If last characters are not matching return isSubsequence(str1, m, str2, n - 1); } // Function to count number of words that // are subsequence of given string S int countSubsequenceWords(string s, vector<string>& arr) { int n = arr.size(); int m = s.length(); int res = 0; for ( int i = 0; i < n; i++) { if (isSubsequence(arr[i], arr[i].size(), s, m)) { res++; } } return res; } // Driver Code int main() { string S = "geeksforgeeks" ; vector<string> arr = { "geek" , "for" , "geekofgeeks" , "gfg" }; // Function call cout << countSubsequenceWords(S, arr) << "\n" ; return 0; } |
Java
// Java code for the above approach: import java.util.*; class GFG { static boolean isSubsequence(String str1, int m, String str2, int n) { if (m == 0 ) return true ; if (n == 0 ) return false ; // If last characters of two strings // are matching if (str1.charAt(m- 1 ) == str2.charAt(n - 1 )) return isSubsequence(str1, m - 1 , str2, n - 1 ); // If last characters are not matching return isSubsequence(str1, m, str2, n - 1 ); } // Function to count number of words that // are subsequence of given string S static int countSubsequenceWords(String s, List<String> arr) { int n = arr.size(); int m = s.length(); int res = 0 ; for ( int i = 0 ; i < n; i++) { if (isSubsequence(arr.get(i), arr.get(i).length(), s, m)) { res++; } } return res; } // Driver Code public static void main(String[] args) { String S = "geeksforgeeks" ; List<String> arr = new ArrayList<String>(); arr.add( "geek" ); arr.add( "for" ); arr.add( "geekofgeeks" ); arr.add( "gfg" ); // Function call System.out.print(countSubsequenceWords(S, arr)); } } // This code is contributed by agrawalpoojaa976. |
Python3
# Python3 code for the above approach # Function to Compare if word is subsequence of string def issubsequence(str1: str , m: int , str2: str , n: int ) - > bool : if m = = 0 : return True if n = = 0 : return False # If last characters of two strings are matching if str1[m - 1 ] = = str2[n - 1 ]: return issubsequence(str1, m - 1 , str2, n - 1 ) # If last characters are not matching return issubsequence(str1, m, str2, n - 1 ) # Function to count number of words # that are subsequence of given string S def countsubsequencewords(s: str , arr: list ) - > int : res = 0 for word in arr: if issubsequence(word, len (word), s, len (s)): res + = 1 return res # Drive code S = "geeksforgeeks" arr = [ "geek" , "for" , "geekofgeeks" , "gfg" ] # Function call print (countsubsequencewords(S, arr)) #This code is contributed by nikhilsainiofficial546 |
C#
using System; using System.Collections.Generic; using System.Linq; class GFG { static bool isSubsequence( string str1, int m, string str2, int n) { if (m == 0) return true ; if (n == 0) return false ; // If last characters of two strings // are matching if (str1[m - 1] == str2[n - 1]) return isSubsequence(str1, m - 1, str2, n - 1); // If last characters are not matching return isSubsequence(str1, m, str2, n - 1); } // Function to count number of words that // are subsequence of given string S static int countSubsequenceWords( string s, string [] arr) { int n = arr.Length; int m = s.Length; int res = 0; for ( int i = 0; i < n; i++) { if (isSubsequence(arr[i], arr[i].Length, s, m)) { res++; } } return res; } // Driver Code public static void Main() { string S = "geeksforgeeks" ; string [] arr = { "geek" , "for" , "geekofgeeks" , "gfg" }; // Function call Console.Write(countSubsequenceWords(S, arr) + "\n" ); } } // This code is contributed by ratiagarwal. |
Javascript
// Javascript code for the above approach: function isSubsequence(str1, m, str2, n) { if (m == 0) return true ; if (n == 0) return false ; // If last characters of two strings // are matching if (str1[m - 1] == str2[n - 1]) return isSubsequence(str1, m - 1, str2, n - 1); // If last characters are not matching return isSubsequence(str1, m, str2, n - 1); } // Function to count number of words that // are subsequence of given string S function countSubsequenceWords(s, arr) { let n = arr.length; let m = s.length; let res = 0; for (let i = 0; i < n; i++) { if (isSubsequence(arr[i], arr[i].length, s, m)) { res++; } } return res; } // Driver Code let S = "geeksforgeeks" ; let arr = [ "geek" , "for" , "geekofgeeks" , "gfg" ]; // Function call console.log(countSubsequenceWords(S, arr)); // This code is contributed by poojaagarwal2. |
3
Time Complexity: O(m*n)
Auxiliary Space: O(m) for recursion stack space
Efficient Approach: The above approach can be optimized based on the following idea:
- Map the index of characters of the given string to the respective characters array.
- Initialize the ans with the size of arr.
- Iterate over all the words in arr one by one.
- Iterate over each character.
- Find strictly greater index than prevIndex in dict.
- If the strictly greater element is not found, it means the current word is not a subsequence of the given string, so decrease res by 1.
- Else update prevIndex.
- After iterating over all the words, return ans.
Below is the implementation of the above approach:
C++
// C++ code for the above approach: #include <bits/stdc++.h> using namespace std; // Function to count number of words that // are subsequence of given string S int countSubsequenceWords(string s, vector<string>& arr) { unordered_map< char , vector< int > > dict; // Mapping index of characters of given // string to respective characters for ( int i = 0; i < s.length(); i++) { dict[s[i]].push_back(i); } // Initializing res with size of arr int res = arr.size(); for ( auto word : arr) { // Index where last character // is found int prevIndex = -1; for ( int j = 0; j < word.size(); j++) { // Searching for strictly // greater element than prev // using binary search auto x = upper_bound(dict[word[j]].begin(), dict[word[j]].end(), prevIndex); // If strictly greater index // not found, the word cannot // be subsequence of string s if (x == dict[word[j]].end()) { res--; break ; } // Else, update the prevIndex else { prevIndex = *x; } } } return res; } // Driver Code int main() { string S = "geeksforgeeks" ; vector<string> arr = { "geek" , "for" , "geekofgeeks" , "gfg" }; // Function call cout << countSubsequenceWords(S, arr) << "\n" ; return 0; } |
Java
import java.util.*; class Main { // Function to count number of words that // are subsequence of given string S static int countSubsequenceWords(String s, List<String> arr) { Map<Character, List<Integer> > dict = new HashMap<>(); // Mapping index of characters of given // string to respective characters for ( int i = 0 ; i < s.length(); i++) { char c = s.charAt(i); List<Integer> list = dict.getOrDefault(c, new ArrayList<>()); list.add(i); dict.put(c, list); } // Initializing res with size of arr int res = arr.size(); for (String word : arr) { // Index where last character // is found int prevIndex = - 1 ; for ( int j = 0 ; j < word.length(); j++) { // Searching for strictly // greater element than prev // using binary search List<Integer> indices = dict.get(word.charAt(j)); int x = binarySearch(indices, prevIndex); // If strictly greater index // not found, the word cannot // be subsequence of string s if (x == - 1 ) { res--; break ; } // Else, update the prevIndex else { prevIndex = indices.get(x); } } } return res; } static int binarySearch(List<Integer> indices, int target) { int l = 0 , r = indices.size() - 1 ; while (l <= r) { int mid = l + (r - l) / 2 ; if (indices.get(mid) <= target) { l = mid + 1 ; } else { r = mid - 1 ; } } return l < indices.size() ? l : - 1 ; } public static void main(String[] args) { String S = "geeksforgeeks" ; List<String> arr = Arrays.asList( "geek" , "for" , "geekofgeeks" , "gfg" ); // Function call System.out.println(countSubsequenceWords(S, arr)); } } // This code is contributed by lokeshpotta20. |
Python3
import collections # Function to count number of words that # are subsequence of given string S def countSubsequenceWords(s, arr): dict = collections.defaultdict( list ) # Mapping index of characters of given # string to respective characters for i in range ( len (s)): dict [s[i]].append(i) # Initializing res with size of arr res = len (arr) for word in arr: # Index where last character # is found prevIndex = - 1 for j in range ( len (word)): # Searching for strictly # greater element than prev # using binary search x = None for i in range ( len ( dict [word[j]])): if dict [word[j]][i] > prevIndex: x = dict [word[j]][i] break # If strictly greater index # not found, the word cannot # be subsequence of string s if x is None : res - = 1 break else : prevIndex = x return res # Driver Code if __name__ = = "__main__" : S = "geeksforgeeks" arr = [ "geek" , "for" , "geekofgeeks" , "gfg" ] # Function call print (countSubsequenceWords(S, arr)) |
C#
// C# code for the above approach: using System; using System.Collections.Generic; public class GFG { // Function to count number of words that // are subsequence of given string S static int CountSubsequenceWords( string s, List< string > arr) { Dictionary< char , List< int > > dict = new Dictionary< char , List< int > >(); // Mapping index of characters of given // string to respective characters for ( int i = 0; i < s.Length; i++) { char c = s[i]; if (!dict.ContainsKey(c)) dict = new List< int >(); dict.Add(i); } // Initializing res with size of arr int res = arr.Count; foreach ( string word in arr) { // Index where last character // is found int prevIndex = -1; for ( int j = 0; j < word.Length; j++) { // Searching for strictly // greater element than prev // using binary search List< int > indices = dict[word[j]]; int x = BinarySearch(indices, prevIndex); // If strictly greater index // not found, the word cannot // be subsequence of string s if (x == -1) { res--; break ; } // Else, update the prevIndex else { prevIndex = indices[x]; } } } return res; } static int BinarySearch(List< int > indices, int target) { int l = 0, r = indices.Count - 1; while (l <= r) { int mid = l + (r - l) / 2; if (indices[mid] <= target) { l = mid + 1; } else { r = mid - 1; } } return l < indices.Count ? l : -1; } static public void Main( string [] args) { string S = "geeksforgeeks" ; List< string > arr = new List< string >{ "geek" , "for" , "geekofgeeks" , "gfg" }; // Function call Console.WriteLine(CountSubsequenceWords(S, arr)); } } // This code is contributed by Prasad Kandekar(prasad264) |
Javascript
// JavaScript code for the above approach: // Function to count number of words that are subsequence of given string S function countSubsequenceWords(s, arr) { let dict = {}; // Mapping index of characters of given string to respective characters for (let i = 0; i < s.length; i++) { let c = s[i]; let list = dict || []; list.push(i); dict = list; } // Initializing res with size of arr let res = arr.length; for (let word of arr) { // Index where last character is found let prevIndex = -1; for (let j = 0; j < word.length; j++) { // Searching for strictly greater element than prev // using binary search let indices = dict[word[j]] || []; let x = binarySearch(indices, prevIndex); // If strictly greater index not found, the word cannot // be subsequence of string s if (x === -1) { res--; break ; } // Else, update the prevIndex else { prevIndex = indices[x]; } } } return res; } function binarySearch(indices, target) { let l = 0, r = indices.length - 1; while (l <= r) { let mid = l + Math.floor((r - l) / 2); if (indices[mid] <= target) { l = mid + 1; } else { r = mid - 1; } } return l < indices.length ? l : -1; } let S = "geeksforgeeks" ; let arr = [ "geek" , "for" , "geekofgeeks" , "gfg" ]; // Function call console.log(countSubsequenceWords(S, arr)); // This code is contributed by lokesh. |
3
Time Complexity: O( m * s * log(n) ), where m is the length of the given string, s is the max length of the word of arr and n is the length of arr
Auxiliary Space: O(n)
Please Login to comment...