1
1
<header >
2
2
<h1 align =" center " >
3
- <a href="https://github.com/guanghechen/algorithm.ts/tree/release-2 .x.x/packages/trie#readme">@algorithm.ts/trie</a>
3
+ <a href="https://github.com/guanghechen/algorithm.ts/tree/release-3 .x.x/packages/trie#readme">@algorithm.ts/trie</a>
4
4
</h1 >
5
5
<div align =" center " >
6
6
<a href="https://www.npmjs.com/package/@algorithm.ts/trie">
@@ -54,13 +54,11 @@ A typescript implementation of the **TRIE** data structure.
54
54
55
55
The following definition is quoted from Wikipedia (https://en.wikipedia.org/wiki/Trie ):
56
56
57
- > In computer science, a trie, also called digital tree or prefix tree, is a
58
- > type of search tree, a tree data structure used for locating specific keys
59
- > from within a set. These keys are most often strings, with links between
60
- > nodes defined not by the entire key, but by individual characters. In order
61
- > to access a key (to recover its value, change it, or remove it), the trie
62
- > is traversed depth-first, following the links between nodes, which
63
- > represent each character in the key.
57
+ > In computer science, a trie, also called digital tree or prefix tree, is a type of search tree, a
58
+ > tree data structure used for locating specific keys from within a set. These keys are most often
59
+ > strings, with links between nodes defined not by the entire key, but by individual characters. In
60
+ > order to access a key (to recover its value, change it, or remove it), the trie is traversed
61
+ > depth-first, following the links between nodes, which represent each character in the key.
64
62
65
63
66
64
## Install
@@ -77,68 +75,66 @@ The following definition is quoted from Wikipedia (https://en.wikipedia.org/wiki
77
75
yarn add @algorithm.ts/trie
78
76
```
79
77
80
- * deno
81
-
82
- ``` typescript
83
- import { createTrie } from ' https://raw.githubusercontent.com/guanghechen/algorithm.ts/main/packages/trie/src/index.ts'
84
- ```
85
78
86
79
## Usage
87
80
88
- * Trie
81
+ * Trie: Trie implements the [ Collection ] [ ] interface.
89
82
90
- - ` init(): void ` : Initialize a trie.
83
+ - ` set(element: Readonly<E>, value: V, start?: number, end?: number): this ` :
84
+ Insert a string (or an array) into the trie.
91
85
92
- - ` insert(str: string, v: T, start?: number, end?: number): void ` : Insert a
93
- string into the trie.
86
+ - ` delete(element: Readonly<E>, start?: number, end?: number): boolean ` :
87
+ Remove a string (or an array) from the trie.
94
88
95
- - ` match(str: string , start?: number, end?: number): T | null ` : Find a word in
96
- the trie which exact match the ` str .slice(start, end)` . If there is such a
97
- word, return its additional value, otherwise return null .
89
+ - ` get(element: Readonly<E> , start?: number, end?: number): V | undefined ` :
90
+ Find the value of the element which exactly matched the ` element .slice(start, end)` .
91
+ If there is no such an element, then return undefined .
98
92
99
- - ` hasPrefixMatched(str: string, start?: number, end?: number): boolean ` :
100
- Check if there is a word ` w ` in the trie satisfied that
101
- ` w.slice(0, end - start) ` equals to ` str.slice(start, end) ` .
93
+ - ` has(element: Readonly<E>, start?: number, end?: number): boolean ` :
94
+ Check if there is an element exactly matched the ` element.slice(start, end) ` .
102
95
103
- - ` find(str: string, start?: number, end?: number): TrieNodeData<T> | null ` :
96
+ - ` hasPrefix(prefix: Readonly<E>, start?: number, end?: number): boolean ` :
97
+ Check if there is an element which prefix matched the ` prefix.slice(start, end) ` .
98
+
99
+ - ` find(element: Readonly<E>, start?: number, end?: number): ITrieNodeData<V> | undefined ` :
104
100
Find word with smallest length in the trie which exact match the
105
- ` str .slice(start, x)` , where the x is an integer in the range [ start, _ end).
101
+ ` element .slice(start, x)` , where the x is an integer in the range [ start, _ end).
106
102
107
- - ` findAll(str: string , start?: number, end?: number): Array<TrieNodeData<T >> ` :
103
+ - ` findAll(element: Readonly<E> , start?: number, end?: number): Iterable<ITrieNodeData<V >> ` :
108
104
Find all words in the trie which exact match the
109
- ` str .slice(start, x)` , where the x is an integer in the range [ start, _ end).
105
+ ` element .slice(start, x)` , where the x is an integer in the range [ start, _ end).
110
106
111
107
* Util
112
108
113
- - ` lowercaseIdx(c: string): number ` : Calc idx of lowercase English letter.
114
- - ` uppercaseIdx(c: string): number ` : Calc idx of uppercase English letter.
115
109
- ` digitIdx(c: string): number ` : Calc idx of digit character.
110
+ - ` uppercaseIdx(c: string): number ` : Calc idx of uppercase English letter.
111
+ - ` lowercaseIdx(c: string): number ` : Calc idx of lowercase English letter.
112
+ - ` alphaNumericIdx(c: string): number ` : Calc idx of digit, lowercase/uppercase English leter.
116
113
117
114
### Example
118
115
119
116
* A solution of https://leetcode.com/problems/word-break-ii/ :
120
117
121
118
``` typescript
122
119
import type { ITrie } from ' @algorithm.ts/trie'
123
- import { createTrie , lowercaseIdx } from ' @algorithm.ts/trie'
120
+ import { Trie , lowercaseIdx } from ' @algorithm.ts/trie'
124
121
125
- export function wordBreak(s : string , wordDict : string []): string [] {
126
- if (s .length <= 0 ) return []
122
+ const trie: ITrie <string , number > = new Trie <string , number >({
123
+ SIGMA_SIZE: 26 ,
124
+ idx: lowercaseIdx ,
125
+ mergeNodeValue : (_x , y ) => y ,
126
+ })
127
127
128
- const trie: ITrie = createTrie ({
129
- SIGMA_SIZE: 26 ,
130
- ZERO: 0 ,
131
- idx: lowercaseIdx ,
132
- mergeAdditionalValues : (x , y ) => y ,
133
- })
128
+ export function wordBreak(text : string , wordDict : string []): string [] {
129
+ if (text .length <= 0 ) return []
134
130
135
- trie .init ()
131
+ trie .clear ()
136
132
for (let i = 0 ; i < wordDict .length ; ++ i ) {
137
133
const word = wordDict [i ]
138
- trie .insert (word , i + 1 )
134
+ trie .set (word , i )
139
135
}
140
136
141
- const N = s .length
137
+ const N = text .length
142
138
const results: string [] = []
143
139
const collect: number [] = []
144
140
dfs (0 , 0 )
@@ -149,14 +145,13 @@ The following definition is quoted from Wikipedia (https://en.wikipedia.org/wiki
149
145
results .push (
150
146
collect
151
147
.slice (0 , cur )
152
- .map (x => wordDict [x - 1 ])
148
+ .map (x => wordDict [x ])
153
149
.join (' ' ),
154
150
)
155
151
return
156
152
}
157
153
158
- const pairs = trie .findAll (s , pos )
159
- for (const { end, val } of pairs ) {
154
+ for (const { end, val } of trie .findAll (text , pos , text .length )) {
160
155
collect [cur ] = val
161
156
dfs (cur + 1 , end )
162
157
}
@@ -167,58 +162,72 @@ The following definition is quoted from Wikipedia (https://en.wikipedia.org/wiki
167
162
* A solution of https://leetcode.com/problems/word-search-ii/
168
163
169
164
``` typescript
170
- import { Trie , createTrie , lowercaseIdx } from ' @algorithm.ts/trie'
165
+ import { Trie , lowercaseIdx } from ' @algorithm.ts/trie'
171
166
172
- function findWords(board : string [][], words : string []): string [] {
173
- if (words .length === 0 ) return []
167
+ class CustomTrie <E extends unknown [] | string , V > extends Trie <E , V > {
168
+ public getSnapshot(): { ch: Uint32Array []; values: Array <V | undefined > } {
169
+ return {
170
+ ch: this ._ch ,
171
+ values: this ._values ,
172
+ }
173
+ }
174
+ }
174
175
175
- const R = board .length
176
- if (R <= 0 ) return []
176
+ const trie = new CustomTrie <string , number >({
177
+ SIGMA_SIZE: 26 ,
178
+ idx: lowercaseIdx ,
179
+ mergeNodeValue : (x , _y ) => x ,
180
+ })
177
181
182
+ export function findWords(board : string [][], words : string []): string [] {
183
+ const N = words .length
184
+ const R = board .length
178
185
const C = board [0 ].length
179
- if (C <= 0 ) return []
186
+ if (N <= 0 || R <= 0 || C <= 0 ) return []
180
187
181
- const trie: Trie = createTrie ({
182
- SIGMA_SIZE: 26 ,
183
- ZERO: 0 ,
184
- idx: lowercaseIdx ,
185
- mergeAdditionalValues : x => x ,
186
- })
188
+ trie .clear ()
189
+ for (let i = 0 ; i < N ; ++ i ) trie .set (words [i ], i )
187
190
188
- trie .init ()
191
+ const boardCode: number [][] = []
192
+ for (let r = 0 ; r < R ; ++ r ) {
193
+ const codes: number [] = []
194
+ for (let c = 0 ; c < C ; ++ c ) codes [c ] = board [r ][c ].charCodeAt (0 ) - 97
195
+ boardCode [r ] = codes
196
+ }
189
197
190
198
const visited: boolean [][] = new Array (R )
191
199
for (let r = 0 ; r < R ; ++ r ) visited [r ] = new Array (C ).fill (false )
192
200
193
- const boardWord: string [] = []
201
+ let matchedWordCount = 0
202
+ const isWordMatched: boolean [] = new Array (N ).fill (false )
203
+
204
+ const { ch, values } = trie .getSnapshot ()
194
205
for (let r = 0 ; r < R ; ++ r ) {
195
206
for (let c = 0 ; c < C ; ++ c ) {
196
207
dfs (0 , r , c )
197
208
}
198
209
}
199
210
200
- const results: string [] = []
201
- for (const word of words ) {
202
- if (trie .hasPrefixMatched (word )) results .push (word )
203
- }
211
+ const results: string [] = words .filter ((_w , i ) => isWordMatched [i ])
204
212
return results
205
213
206
- function dfs(cur : number , r : number , c : number ): void {
207
- if (cur === 10 || r < 0 || r >= R || c < 0 || c >= C ) {
208
- trie .insert (boardWord .join (' ' ), 1 , 0 , cur )
209
- return
210
- }
214
+ function dfs(u : number , r : number , c : number ): void {
215
+ if (visited [r ][c ] || matchedWordCount === N ) return
211
216
212
- if (visited [r ][c ]) return
217
+ const u2: number = ch [u ][boardCode [r ][c ]]
218
+ if (u2 === 0 ) return
213
219
214
- visited [r ][c ] = true
215
- boardWord [cur ] = board [r ][c ]
220
+ const val = values [u2 ]
221
+ if (val !== undefined && ! isWordMatched [val ]) {
222
+ isWordMatched [val ] = true
223
+ matchedWordCount += 1
224
+ }
216
225
217
- const nextCur : number = cur + 1
218
- dfs (nextCur , r - 1 , c )
219
- dfs (nextCur , r , c + 1 )
220
- dfs (nextCur , r + 1 , c )
221
- dfs (nextCur , r , c - 1 )
226
+ visited [ r ][ c ] = true
227
+ if ( r > 0 ) dfs (u2 , r - 1 , c )
228
+ if ( c + 1 < C ) dfs (u2 , r , c + 1 )
229
+ if ( r + 1 < R ) dfs (u2 , r + 1 , c )
230
+ if ( c > 0 ) dfs (u2 , r , c - 1 )
222
231
visited [r ][c ] = false
223
232
}
224
233
}
@@ -229,4 +238,5 @@ The following definition is quoted from Wikipedia (https://en.wikipedia.org/wiki
229
238
* https://en.wikipedia.org/wiki/Trie
230
239
231
240
232
- [ homepage ] : https://github.com/guanghechen/algorithm.ts/tree/release-2.x.x/packages/trie#readme
241
+ [ homepage ] : https://github.com/guanghechen/algorithm.ts/tree/release-3.x.x/packages/trie#readme
242
+ [ Collection ] : https://github.com/guanghechen/algorithm.ts/tree/release-3.x.x/packages/types#readme
0 commit comments