Count the strings that are subsequence of the given string
Last Updated :
21 Feb, 2023
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++
#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 (str1[m - 1] == str2[n - 1])
return isSubsequence(str1, m - 1, str2, n - 1);
return isSubsequence(str1, m, str2, n - 1);
}
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;
}
int main()
{
string S = "geeksforgeeks" ;
vector<string> arr
= { "geek" , "for" , "geekofgeeks" , "gfg" };
cout << countSubsequenceWords(S, arr) << "\n" ;
return 0;
}
|
Java
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 (str1.charAt(m- 1 ) == str2.charAt(n - 1 ))
return isSubsequence(str1, m - 1 , str2, n - 1 );
return isSubsequence(str1, m, str2, n - 1 );
}
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;
}
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" );
System.out.print(countSubsequenceWords(S, arr));
}
}
|
Python3
def issubsequence(str1: str , m: int , str2: str , n: int ) - > bool :
if m = = 0 :
return True
if n = = 0 :
return False
if str1[m - 1 ] = = str2[n - 1 ]:
return issubsequence(str1, m - 1 , str2, n - 1 )
return issubsequence(str1, m, str2, n - 1 )
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
S = "geeksforgeeks"
arr = [ "geek" , "for" , "geekofgeeks" , "gfg" ]
print (countsubsequencewords(S, arr))
|
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 (str1[m - 1] == str2[n - 1])
return isSubsequence(str1, m - 1, str2, n - 1);
return isSubsequence(str1, m, str2, n - 1);
}
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;
}
public static void Main()
{
string S = "geeksforgeeks" ;
string [] arr = { "geek" , "for" , "geekofgeeks" , "gfg" };
Console.Write(countSubsequenceWords(S, arr) + "\n" );
}
}
|
Javascript
function isSubsequence(str1, m, str2, n)
{
if (m == 0)
return true ;
if (n == 0)
return false ;
if (str1[m - 1] == str2[n - 1])
return isSubsequence(str1, m - 1, str2, n - 1);
return isSubsequence(str1, m, str2, n - 1);
}
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;
}
let S = "geeksforgeeks" ;
let arr = [ "geek" , "for" , "geekofgeeks" , "gfg" ];
console.log(countSubsequenceWords(S, arr));
|
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++
#include <bits/stdc++.h>
using namespace std;
int countSubsequenceWords(string s, vector<string>& arr)
{
unordered_map< char , vector< int > > dict;
for ( int i = 0; i < s.length(); i++) {
dict[s[i]].push_back(i);
}
int res = arr.size();
for ( auto word : arr) {
int prevIndex = -1;
for ( int j = 0; j < word.size(); j++) {
auto x = upper_bound(dict[word[j]].begin(),
dict[word[j]].end(),
prevIndex);
if (x == dict[word[j]].end()) {
res--;
break ;
}
else {
prevIndex = *x;
}
}
}
return res;
}
int main()
{
string S = "geeksforgeeks" ;
vector<string> arr
= { "geek" , "for" , "geekofgeeks" , "gfg" };
cout << countSubsequenceWords(S, arr) << "\n" ;
return 0;
}
|
Java
import java.util.*;
class Main
{
static int countSubsequenceWords(String s, List<String> arr) {
Map<Character, List<Integer> > dict = new HashMap<>();
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);
}
int res = arr.size();
for (String word : arr)
{
int prevIndex = - 1 ;
for ( int j = 0 ; j < word.length(); j++)
{
List<Integer> indices = dict.get(word.charAt(j));
int x = binarySearch(indices, prevIndex);
if (x == - 1 ) {
res--;
break ;
}
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" );
System.out.println(countSubsequenceWords(S, arr));
}
}
|
Python3
import collections
def countSubsequenceWords(s, arr):
dict = collections.defaultdict( list )
for i in range ( len (s)):
dict [s[i]].append(i)
res = len (arr)
for word in arr:
prevIndex = - 1
for j in range ( len (word)):
x = None
for i in range ( len ( dict [word[j]])):
if dict [word[j]][i] > prevIndex:
x = dict [word[j]][i]
break
if x is None :
res - = 1
break
else :
prevIndex = x
return res
if __name__ = = "__main__" :
S = "geeksforgeeks"
arr = [ "geek" , "for" , "geekofgeeks" , "gfg" ]
print (countSubsequenceWords(S, arr))
|
C#
using System;
using System.Collections.Generic;
public class GFG
{
static int CountSubsequenceWords( string s,
List< string > arr)
{
Dictionary< char , List< int > > dict
= new Dictionary< char , List< int > >();
for ( int i = 0; i < s.Length; i++) {
char c = s[i];
if (!dict.ContainsKey(c))
dict = new List< int >();
dict.Add(i);
}
int res = arr.Count;
foreach ( string word in arr)
{
int prevIndex = -1;
for ( int j = 0; j < word.Length; j++) {
List< int > indices = dict[word[j]];
int x = BinarySearch(indices, prevIndex);
if (x == -1) {
res--;
break ;
}
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" };
Console.WriteLine(CountSubsequenceWords(S, arr));
}
}
|
Javascript
function countSubsequenceWords(s, arr) {
let dict = {};
for (let i = 0; i < s.length; i++) {
let c = s[i];
let list = dict || [];
list.push(i);
dict = list;
}
let res = arr.length;
for (let word of arr) {
let prevIndex = -1;
for (let j = 0; j < word.length; j++) {
let indices = dict[word[j]] || [];
let x = binarySearch(indices, prevIndex);
if (x === -1) {
res--;
break ;
}
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" ];
console.log(countSubsequenceWords(S, arr));
|
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
Share your thoughts in the comments
Please Login to comment...