@tanishiking/aho-corasick
Version:
TypeScript implementation of the Aho-Corasick algorithm for efficient string matching
108 lines (107 loc) • 4.25 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.IntervalNode = void 0;
var Direction;
(function (Direction) {
Direction[Direction["Right"] = 0] = "Right";
Direction[Direction["Left"] = 1] = "Left";
})(Direction || (Direction = {}));
/**
* Binary tree to find all intervals that overlaps with the given interval efficiently.
*/
var IntervalNode = /** @class */ (function () {
/**
*
* @param intervals intervals, note that they should be sorted by size decending.
*/
function IntervalNode(intervals) {
var _this = this;
this.intervals = [];
this.left = null;
this.right = null;
this.medianPoint = this.determineMedian(intervals);
var toLeft = [];
var toRight = [];
intervals.forEach(function (interval) {
if (interval.end < _this.medianPoint) {
toLeft.push(interval);
}
else if (_this.medianPoint < interval.start) {
toRight.push(interval);
}
else {
_this.intervals.push(interval);
}
});
if (toLeft.length > 0)
this.left = new IntervalNode(toLeft);
if (toRight.length > 0)
this.right = new IntervalNode(toRight);
}
/**
* Find all intervals overlap with the given interval.
*
* @param interval - the interval object to find its overlaps.
*/
IntervalNode.prototype.findOverlaps = function (interval) {
if (this.medianPoint < interval.start) {
var fromRightChild = this.right !== null ? this.right.findOverlaps(interval) : [];
var fromThisNode = this.checkForOverlaps(interval, Direction.Right);
return fromRightChild.concat(fromThisNode).filter(function (current) { return !interval.equals(current); });
}
else if (interval.end < this.medianPoint) {
var fromLeftChild = this.left !== null ? this.left.findOverlaps(interval) : [];
var fromThisNode = this.checkForOverlaps(interval, Direction.Left);
return fromLeftChild.concat(fromThisNode).filter(function (current) { return !interval.equals(current); });
}
else {
var fromRightChild = this.right !== null ? this.right.findOverlaps(interval) : [];
var fromLeftChild = this.left !== null ? this.left.findOverlaps(interval) : [];
return this.intervals
.concat(fromRightChild)
.concat(fromLeftChild)
.filter(function (current) { return !interval.equals(current); });
}
};
/**
* Find the intervals that overlaps with the given interval (which never contains median point)
* from the intervals of this node (which always contains median point).
* median
* ---------------------o---------------------
* given interval ------[xxxxxxx]--------------[xxxxx]-------
* current ------------[xxxxxxxxxxxxxxxxxxx]----------
*
* @param interval - the interval to find its overlaps.
* @param direction - the direction to search for.
*/
IntervalNode.prototype.checkForOverlaps = function (interval, direction) {
return this.intervals.filter(function (current) {
if (direction === Direction.Left)
return current.start <= interval.end;
else
return current.end >= interval.start;
});
};
/**
* Find a median point from left most start and right most ends.
*
* @param intervals
*/
IntervalNode.prototype.determineMedian = function (intervals) {
var start = -1;
var end = -1;
intervals.forEach(function (interval) {
var currentStart = interval.start;
var currentEnd = interval.end;
if (start === -1 || currentStart < start) {
start = currentStart;
}
if (end === -1 || currentEnd > end) {
end = currentEnd;
}
});
return Math.floor((start + end) / 2);
};
return IntervalNode;
}());
exports.IntervalNode = IntervalNode;