Warning: session_start(): open(/var/lib/php/sessions/sess_ld4p5ovibrlql6115hdmcv63ev, O_RDWR) failed: No space left on device (28) in /var/www/tb-usercake/models/config.php on line 51
Warning: session_start(): Failed to read session data: files (path: /var/lib/php/sessions) in /var/www/tb-usercake/models/config.php on line 51
sclass SuffixTree {
Node root;
S fullText;
Comparator childComparator = (a, b) -> a.firstCharOrMinus1()-b.firstCharOrMinus1();
new DummyNode dummyNode;
sinterface IFirstChar {
int firstCharOrMinus1();
}
sclass DummyNode implements IFirstChar {
int firstChar;
public int firstCharOrMinus1() { ret firstChar; }
}
sclass Node implements IFirstChar {
Substring text;
CompactTreeSet children; // actually,
IntBuffer positions;
*() {}
*(Substring *text) {}
void addPosition(int i) {
if (positions == null) positions = new IntBuffer;
positions.add(i);
}
void addChild(SuffixTree tree, Node n) {
if (children == null) children = makeEmptyChildrenSet(tree);
children.add(n);
}
CompactTreeSet makeEmptyChildrenSet(SuffixTree tree) { ret new CompactTreeSet<>(tree.childComparator); }
public int firstCharOrMinus1() {
ret charToIntOrMinus1(text);
}
Node getChild(SuffixTree tree, int c) {
if (children == null) null;
tree.dummyNode.firstChar = c;
ret (Node) children.find(tree.dummyNode);
}
}
*() {}
*(S *fullText) {
root = new Node(Substring(fullText, 0, 0));
for i over fullText:
addSuffix(Substring(fullText, i), i);
}
void addSuffix(Substring s, int position) {
Node node = root;
while (!empty(s)) {
int _n = lCommonPrefix_CharSequence(node.text, s);
s = s.substring(_n);
if (_n >= l(node.text)) { // node text exhausted
if (empty(s)) {
node.addPosition(position);
ret;
} else {
Node n = node.getChild(SuffixTree.this, charToIntOrMinus1(s));
if (n == null) {
n = new Node(s);
n.addPosition(position);
node.addChild(SuffixTree.this, n);
ret;
} else
node = n;
}
} else { // node text not exhausted
// split node. first, move all the node's vitals to a new node nOld
Node nOld = new Node(node.text.substring(_n));
nOld.positions = node.positions;
node.positions = null;
nOld.children = node.children;
node.children = null;
node.text = node.text.substring(0, _n);
node.addChild(SuffixTree.this, nOld);
// now add a new node
Node nNew = new Node(s);
nNew.addPosition(position);
node.addChild(SuffixTree.this, nNew);
ret;
}
}
}
public L indicesOf(S pattern) {
new IntBuffer out;
getIndicesOf(out, root, pattern, 0);
ret out.asVirtualList();
}
void getIndicesOf(IntBuffer out, Node node, S pattern, int iPattern) {
int lPattern = l(pattern);
while true {
int n = lCommonPrefix_CharSequence(node.text, Substring(pattern, iPattern));
iPattern += n;
if (iPattern >= lPattern) break;
if (n < l(node.text)) break;
Node child = node.getChild(SuffixTree.this, charAtAsIntOrMinus1(pattern, iPattern));
if (child != null) node = child;
}
collectPositions(out, node);
}
L getPositions(Node node) {
new IntBuffer out;
collectPositions(out, node);
ret out.asVirtualList();
}
void collectPositions(IntBuffer out, Node node) {
if (node == null) ret;
out.addAll(node.positions);
fOr (Node n : values(node.children))
collectPositions(out, n);
}
void printMe() {
printNode("", "", root);
}
void printNode(S indent, S pre, Node node) {
print(indent + pre + quote(shorten(20, node.text)) + (empty(node.positions) ? "" : " " + node.positions));
fOr (Node n : node.children)
printNode(indent + " ", "[" + (empty(n.text) ? "end" : quote(n.text.charAt(0)) + "] ", n);
}
}