Skip to content

Commit 7cf0879

Browse files
authored
Create 792 - Number of Matching Subsequences.md
1 parent a200784 commit 7cf0879

File tree

1 file changed

+140
-0
lines changed

1 file changed

+140
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
---
2+
id: number-of-matching-subsequences
3+
title: Number of Matching Subsequences
4+
sidebar_label: 792 - Number of Matching Subsequences
5+
tags: [Trie, Two Pointers, Hash Table, C++, Java, Python]
6+
description: Solve the problem of counting the number of words that are subsequences of a given string using various efficient methods.
7+
---
8+
9+
## Problem Statement
10+
11+
### Problem Description
12+
13+
You are given a string `s` and an array of strings `words`. The task is to return the number of `words[i]` that are subsequences of `s`.
14+
15+
A subsequence of a string is a new string generated from the original string with some characters (can be none) deleted without changing the relative order of the remaining characters.
16+
17+
For example, "ace" is a subsequence of "abcde".
18+
19+
### Example
20+
21+
**Example 1:**
22+
```
23+
Input: s = "abcde", words = ["a","bb","acd","ace"]
24+
Output: 3
25+
```
26+
27+
**Explanation:** There are three strings in `words` that are subsequences of `s`: "a", "acd", "ace".
28+
29+
**Example 2:**
30+
```
31+
Input: s = "dsahjpjauf", words = ["ahjpjau","ja","ahbwzgqnuk","tnmlanowax"]
32+
Output: 2
33+
```
34+
35+
### Constraints
36+
37+
- $1 \leq \text{s.length} \leq 5 \times 10^4$
38+
- $1 \leq \text{words.length} \leq 5000$
39+
- $1 \leq \text{words[i].length} \leq 50$
40+
- `s` and `words[i]` consist of only lowercase English letters.
41+
42+
## Solution
43+
44+
### Intuition
45+
46+
To efficiently count the number of subsequences, we can use different methods, including Trie, Two Pointers, and Hash Table. The goal is to check for each word in `words` whether it can be formed as a subsequence of `s`.
47+
48+
### Methods
49+
50+
#### Method 1: Two Pointers
51+
52+
For each word in `words`, we can use two pointers to check if it is a subsequence of `s`. One pointer iterates through `s`, and the other iterates through the current word. We match characters and advance both pointers accordingly.
53+
54+
**Time Complexity:**
55+
The time complexity is $O(n \cdot m)$, where `n` is the length of `s` and `m` is the total number of characters in `words`.
56+
57+
#### Method 2: Hash Table and Bucketing
58+
59+
We can use a hash table where each key is a character from `a` to `z` and each value is a list of iterators. For each character in `s`, we update the hash table to see if there are any words that can progress to the next character.
60+
61+
**Time Complexity:**
62+
The time complexity is $O(n + m)$, where `n` is the length of `s` and `m` is the total length of all words in `words`.
63+
64+
### Code
65+
66+
#### C++
67+
68+
```cpp
69+
class Solution {
70+
public:
71+
int numMatchingSubseq(string s, vector<string>& words) {
72+
vector<vector<int>> waiting(128);
73+
for (int i = 0; i < words.size(); ++i) {
74+
waiting[words[i][0]].push_back(i);
75+
}
76+
77+
int res = 0;
78+
for (char c : s) {
79+
vector<int> advance = move(waiting[c]);
80+
waiting[c].clear();
81+
for (int idx : advance) {
82+
if (++words[idx].length() == words[idx].size()) {
83+
++res;
84+
} else {
85+
waiting[words[idx][words[idx].length()]].push_back(idx);
86+
}
87+
}
88+
}
89+
return res;
90+
}
91+
};
92+
```
93+
#### Java
94+
```java
95+
class Solution {
96+
public int numMatchingSubseq(String s, String[] words) {
97+
List<int[]>[] waiting = new ArrayList[128];
98+
for (int c = 0; c <= 127; ++c) {
99+
waiting[c] = new ArrayList<>();
100+
}
101+
for (int i = 0; i < words.length; ++i) {
102+
waiting[words[i].charAt(0)].add(new int[]{i, 1});
103+
}
104+
105+
int res = 0;
106+
for (char c : s.toCharArray()) {
107+
List<int[]> advance = waiting[c];
108+
waiting[c] = new ArrayList<>();
109+
for (int[] arr : advance) {
110+
if (arr[1] == words[arr[0]].length()) {
111+
++res;
112+
} else {
113+
waiting[words[arr[0]].charAt(arr[1]++)].add(arr);
114+
}
115+
}
116+
}
117+
return res;
118+
}
119+
}
120+
```
121+
#### Python
122+
```python
123+
class Solution:
124+
def numMatchingSubseq(self, s: str, words: List[str]) -> int:
125+
from collections import defaultdict
126+
waiting = defaultdict(list)
127+
for i, word in enumerate(words):
128+
waiting[word[0]].append((i, 1))
129+
130+
res = 0
131+
for c in s:
132+
advance = waiting[c]
133+
waiting[c] = []
134+
for i, j in advance:
135+
if j == len(words[i]):
136+
res += 1
137+
else:
138+
waiting[words[i][j]].append((i, j + 1))
139+
return res
140+
```

0 commit comments

Comments
 (0)