73 lines
1.9 KiB
JavaScript
73 lines
1.9 KiB
JavaScript
|
(function (exports) {
|
||
|
'use strict';
|
||
|
|
||
|
function Node(val) {
|
||
|
this.value = val;
|
||
|
this.nodes = {};
|
||
|
}
|
||
|
|
||
|
function SuffixTree() {
|
||
|
this.root = new Node();
|
||
|
}
|
||
|
|
||
|
SuffixTree.prototype.addNode = (function () {
|
||
|
|
||
|
function maxPrefix(a, b) {
|
||
|
var res = [];
|
||
|
for (var i = 0; i < Math.min(a.length, b.length); i += 1) {
|
||
|
if (a[i] === b[i]) {
|
||
|
res.push(a[i]);
|
||
|
} else {
|
||
|
return '';
|
||
|
}
|
||
|
}
|
||
|
return res.join('');
|
||
|
}
|
||
|
|
||
|
function addNode(suffix, current) {
|
||
|
// Empty string already exists in the suffix tree
|
||
|
if (!suffix) {
|
||
|
return;
|
||
|
}
|
||
|
// The suffix is already inside the tree
|
||
|
if (current.value === suffix) {
|
||
|
return;
|
||
|
}
|
||
|
// Insert recursively
|
||
|
if (current.nodes[suffix[0]]) {
|
||
|
return addNode(suffix.substr(1, suffix.length),
|
||
|
current.nodes[suffix[0]]);
|
||
|
}
|
||
|
// Find the maximum prefix and split the current node if prefix exists
|
||
|
var prefix = maxPrefix(current.value, suffix);
|
||
|
if (prefix.length) {
|
||
|
var temp = current.value;
|
||
|
var suffixSuffix = suffix.substr(prefix.length, suffix.length);
|
||
|
var currentSuffix = temp.substr(prefix.length, temp.length);
|
||
|
current.value = prefix;
|
||
|
addNode(currentSuffix, current);
|
||
|
addNode(suffixSuffix, current);
|
||
|
// If prefix doesn't exists add new child node
|
||
|
} else {
|
||
|
current.nodes[suffix[0]] = new Node(suffix);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return function (suffix) {
|
||
|
addNode(suffix, this.root);
|
||
|
};
|
||
|
}());
|
||
|
|
||
|
// O(n^2) or even O(n^3) because of maxPrefix
|
||
|
SuffixTree.prototype.build = function (string) {
|
||
|
this.root.value = string;
|
||
|
for (var i = 1; i < string.length; i += 1) {
|
||
|
this.addNode(string.substr(i, string.length));
|
||
|
}
|
||
|
};
|
||
|
|
||
|
exports.Node = Node;
|
||
|
exports.SuffixTree = SuffixTree;
|
||
|
|
||
|
}(typeof exports === 'undefined' ? window : exports));
|