You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

91 lines
2.6 KiB

2 years ago
var Class = require('./Class');
var each = require('./each');
exports = Class({
initialize: function Trie() {
this.clear();
},
add: function(word) {
var edges = this._edges;
var node = this._root;
this._wordsInSubtree[node]++;
for (var i = 0, len = word.length; i < len; i++) {
var edge = word[i];
var next = edges[node][edge];
if (!next) {
if (this._freeNodes.length) {
next = this._freeNodes.pop();
} else {
next = this._idx++;
this._isWord.push(false);
this._wordsInSubtree.push(0);
edges.push({});
}
edges[node][edge] = next;
}
this._wordsInSubtree[next]++;
node = next;
}
this._isWord[node] = true;
},
remove: function(word) {
if (!this.has(word)) {
return;
}
var node = this._root;
this._wordsInSubtree[node]--;
for (var i = 0, len = word.length; i < len; i++) {
var edge = word[i];
var next = this._edges[node][edge];
if (!--this._wordsInSubtree[next]) {
delete this._edges[node][edge];
this._freeNodes.push(next);
}
node = next;
}
this._isWord[node] = false;
},
has: function(word) {
var node = this._root;
for (var i = 0, len = word.length; i < len; i++) {
node = this._edges[node][word[i]];
if (!node) {
return false;
}
}
return this._isWord[node];
},
words: function(prefix) {
var node = this._root;
for (var i = 0, len = prefix.length; i < len; i++) {
node = this._edges[node][prefix[i]];
if (!node) {
return [];
}
}
var result = [];
this._dfs(node, prefix, result);
return result;
},
clear: function() {
this._idx = 1;
this._root = 0;
this._edges = [{}];
this._isWord = [false];
this._wordsInSubtree = [0];
this._freeNodes = [];
},
_dfs: function(node, prefix, result) {
var _this = this;
if (this._isWord[node]) {
result.push(prefix);
}
var edges = this._edges[node];
each(edges, function(node, edge) {
return _this._dfs(node, prefix + edge, result);
});
}
});
module.exports = exports;