Skip to content

Commit 9588277

Browse files
committed
add optimzied trie merging fun solution
1 parent 70a45ab commit 9588277

File tree

3 files changed

+52
-7
lines changed

3 files changed

+52
-7
lines changed

my-submissions/m792 v1.py renamed to my-submissions/m792 v1 dfs parallel index tracking.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,8 @@ def _dfs_trie(self,
3030
continue
3131
if nxt_c == "." :
3232
continue
33-
3433
char_ord = ord(nxt_c) - ord('a')
35-
previous_rec = c_indxes[char_ord]
34+
prev_reset = c_indxes[char_ord]
3635

3736
if c_indxes[char_ord] >= len(s_indxes[nxt_c]) :
3837
continue
@@ -43,16 +42,16 @@ def _dfs_trie(self,
4342
break
4443

4544
if c_indxes[char_ord] >= len(s_indxes[nxt_c]) :
46-
c_indxes[char_ord] = previous_rec
45+
c_indxes[char_ord] = prev_reset
4746
continue
4847

4948
c_indxes[char_ord] += 1
5049
output += self._dfs_trie(
51-
nxt_trie,
52-
s_indxes,
53-
c_indxes,
50+
nxt_trie,
51+
s_indxes,
52+
c_indxes,
5453
s_indxes[nxt_c][c_indxes[char_ord] - 1] + 1
5554
)
56-
c_indxes[char_ord] = previous_rec
55+
c_indxes[char_ord] = prev_reset
5756

5857
return output
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
class Solution:
2+
def numMatchingSubseq(self, s: str, words: List[str]) -> int:
3+
trie = {}
4+
for w in words :
5+
curr = trie
6+
for c in w :
7+
if c not in curr :
8+
curr[c] = {}
9+
curr = curr[c]
10+
# Mark ends of words; +1 in case there are repeats
11+
curr["."] = curr.get(".", 0) + 1
12+
13+
for c in s :
14+
if c not in trie :
15+
continue
16+
# Remove the char branch and merge its subtrie contents into main trie
17+
self._trie_merger_helper(trie, trie.pop(c))
18+
19+
return trie['.']
20+
21+
def _trie_merger_helper(self, trie1: Dict[str, dict], trie2: Dict[str, dict]) -> None :
22+
# Merge our "success" counter
23+
if '.' in trie2 :
24+
trie1['.'] = trie1.get('.', 0) + trie2.get('.', 0)
25+
trie2.pop('.')
26+
27+
# Merge branches of trie
28+
for k, v in trie2.items() :
29+
if k not in trie1 : # If doesn't exist, we can reuse directly
30+
trie1[k] = v
31+
continue
32+
33+
# Recurse into branches
34+
self._trie_merger_helper(trie1[k], trie2[k])

my-submissions/m792.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
## V1 DFS Parallel Index Tracking
2+
3+
Indexes the indices of each character in `s` and creates a trie of
4+
all potential subsequence words. Then, performs a DFS on the subsequence word trie while tracking the "last used index" of each character to see if each is valid.
5+
6+
Runtime: $O(s+w*v*s)$ where $s$ is the length of input string `s` and $w$ is the number of subsequence candidates in `words` and $v$ is the longest candidate in `words`.
7+
8+
## V2 Trie-Merging Recursion
9+
10+
Converts potential subsequence word targets into a trie then iterates through each character of `s`. At each character `c`, if it's in the trie, we remove it and merge the subtrie into the main trie root. That is, we merge `trie[c]` into the root `trie` and recursively merge the branches. We use `trie['.']` to track how many word "endings" we have. Since we're systematically eliminating letters and summing `trie['.']` we return `'.'` which is our counter.
11+
12+
Runtime: $O(s)$ where $s$ is the length of the input string `s`.

0 commit comments

Comments
 (0)