Open In App

Count the strings that are subsequence of the given string

Last Updated : 21 Feb, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

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.


Output

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.


Output

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)



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads