[Algorithm] Search for matching words

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 [dogdeerdeal], return [deerdeal].

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();

猜你喜欢

转载自www.cnblogs.com/Answer1215/p/10548079.html