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