Implement an autocomplete system. That is, given a query string
s
and a set of all possible query strings, return all strings in the set that have s as a prefix.For example, given the query string
de
and the set of strings [dog
,deer
,deal
], return [deer
,deal
].Hint: Try preprocessing the dictionary into a more efficient data structure to speed up queries.
It is using the Trie data stucture, check thist post;
The only changes is that when we search for words, it is partially matched + whole word match.
Which means if we search 'de', it should return [deer, deal],
if we search 'deer', it should return [deer],
if we search 'deerr', it should return [].
function Node () { return { keys: new Map(), isEnd: false } } function Trie () { return { root: new Node(), // Add words into the tree // Recursive add(word, node = this.root) { // If there is no word, means it reach the end if (word.length === 0) { node.isEnd = true; return; } const [head, ...rest] = word; // If char is not set, then create a new Node to hold char // Otherwise, continue if (!node.keys.has(head)) { node.keys.set(head, new Node(head)); } // Continue with three this.add(rest, node.keys.get(head)); }, // Print all the words in the tree print () { let words = []; // Helper function, Recursive function search (node = this.root, string = '') { // Make sure we have keys if (node.keys.size !== 0) { for (let key of node.keys.keys()) { // update node, update string search(node.keys.get(key), string.concat(key)); } // if reach the end, push to the words if (node.isEnd) { words.push(string); } } else { // If there is no keys, then push the avaialbe string to the words string.length > 0 ? words.push(string) : null; } } search(this.root, ''); return words.length > 0 ? words : null; }, // Find the words based on input find (input) { let words = []; function search(node = this.root, string = '', input) { if (node.keys.size !== 0) { for (let key of node.keys.keys()) { // if the key is the same as input[0] // becasue we want the whole word, so continue with current trees if (key === input[0] || input.length === 0) { let rest = input.length === 0 ? '': input.substr(1); search(node.keys.get(key), string.concat(key), rest); } } } else { // In case of input is 'cattt', then return undefined if (input.length !== 0) { return []; } string.length > 0 ? words.push(string) : []; } } search(this.root, '', input); return words.length > 0 ? words : []; } } } function searchWords () { const data = ['dog', 'dollar', 'cat', 'drag']; const trie = new Trie(); data.forEach(d => trie.add(d)); console.log(trie.find('do')); // [ 'dog', 'dollar' ] console.log(trie.print()); // [ 'dog', 'dollar', 'drag', 'cat' ] } searchWords();