@@ -3,9 +3,10 @@ import {
3
3
readGzippedJSON ,
4
4
TRIE_FILE ,
5
5
TSV_DB_FILE ,
6
+ uniteSets ,
6
7
writeGzippedJSON ,
7
8
} from "./util.js" ;
8
- import { readFileSync , writeFileSync } from "fs" ;
9
+ import { readFileSync } from "fs" ;
9
10
10
11
interface EncodedTrieNode {
11
12
c ?: Record < string , EncodedTrieNode > ;
@@ -70,6 +71,64 @@ export class Trie {
70
71
return currentNode ;
71
72
}
72
73
74
+ findLastNodeMatch ( query : string ) {
75
+ // Initialize the currentNode pointer with the root node
76
+ let currentNode = this . root ;
77
+
78
+ let i = 0 ;
79
+ // Iterate across the length of the string
80
+ for ( i = 0 ; i < query . length ; i ++ ) {
81
+ const c = query [ i ] as string ;
82
+ // Check if the node exist for the current character in the Trie.
83
+ if ( ! currentNode . children [ c ] ) {
84
+ // Given word as a prefix does not exist in Trie
85
+ return { currentNode, i } ;
86
+ }
87
+
88
+ // Move the currentNode pointer to the already existing node for current character.
89
+ currentNode = currentNode . children [ c ] ;
90
+ }
91
+
92
+ // Prefix exist in the Trie
93
+ return { currentNode, i } ;
94
+ }
95
+
96
+ autocomplete ( query : string , maxResultCount = 10 ) {
97
+ const resultSet = new Set < number > ( ) ;
98
+
99
+ const { i, currentNode } = this . findLastNodeMatch ( query ) ;
100
+ this . collectLineNumbersWithBFS (
101
+ currentNode ,
102
+ query . length ,
103
+ i ,
104
+ resultSet ,
105
+ maxResultCount ,
106
+ ) ;
107
+ return resultSet ;
108
+ }
109
+
110
+ collectLineNumbersWithBFS (
111
+ currentNode : TrieNode ,
112
+ querySize : number ,
113
+ queryIndex : number ,
114
+ resultSet : Set < number > ,
115
+ maxResultCount = 10 ,
116
+ ) {
117
+ if ( resultSet . size > maxResultCount ) return ;
118
+ uniteSets ( resultSet , currentNode . lineNumbers ) ;
119
+ if ( queryIndex >= querySize ) return ;
120
+
121
+ for ( const [ _ , childNode ] of Object . entries ( currentNode . children ) ) {
122
+ this . collectLineNumbersWithBFS (
123
+ childNode ,
124
+ querySize ,
125
+ queryIndex ++ ,
126
+ resultSet ,
127
+ maxResultCount ,
128
+ ) ;
129
+ }
130
+ }
131
+
73
132
searchPrefix ( query : string ) : number [ ] | null {
74
133
const searchTerm = query . trim ( ) . toLowerCase ( ) ;
75
134
if ( searchTerm . length < 1 ) return null ;
0 commit comments