Trie.js 1.7 KB

1234567891011121314151617181920
  1. export class Trie{constructor(){this.clear();}
  2. add(word){let node=this._root;++this._wordsInSubtree[this._root];for(let i=0;i<word.length;++i){const edge=word[i];let next=this._edges[node][edge];if(!next){if(this._freeNodes.length){next=this._freeNodes.pop();}else{next=this._size++;this._isWord.push(false);this._wordsInSubtree.push(0);this._edges.push({__proto__:null});}
  3. this._edges[node][edge]=next;}
  4. ++this._wordsInSubtree[next];node=next;}
  5. this._isWord[node]=true;}
  6. remove(word){if(!this.has(word)){return false;}
  7. let node=this._root;--this._wordsInSubtree[this._root];for(let i=0;i<word.length;++i){const edge=word[i];const next=this._edges[node][edge];if(!--this._wordsInSubtree[next]){delete this._edges[node][edge];this._freeNodes.push(next);}
  8. node=next;}
  9. this._isWord[node]=false;return true;}
  10. has(word){let node=this._root;for(let i=0;i<word.length;++i){node=this._edges[node][word[i]];if(!node){return false;}}
  11. return this._isWord[node];}
  12. words(prefix){prefix=prefix||'';let node=this._root;for(let i=0;i<prefix.length;++i){node=this._edges[node][prefix[i]];if(!node){return[];}}
  13. const results=[];this._dfs(node,prefix,results);return results;}
  14. _dfs(node,prefix,results){if(this._isWord[node]){results.push(prefix);}
  15. const edges=this._edges[node];for(const edge in edges){this._dfs(edges[edge],prefix+edge,results);}}
  16. longestPrefix(word,fullWordOnly){let node=this._root;let wordIndex=0;for(let i=0;i<word.length;++i){node=this._edges[node][word[i]];if(!node){break;}
  17. if(!fullWordOnly||this._isWord[node]){wordIndex=i+1;}}
  18. return word.substring(0,wordIndex);}
  19. clear(){this._size=1;this._root=0;this._edges=[{__proto__:null}];this._isWord=[false];this._wordsInSubtree=[0];this._freeNodes=[];}}
  20. self.Common=self.Common||{};Common=Common||{};Common.Trie=Trie;