public static SuffixTree create(Text text) { SuffixTree tree = new SuffixTree(text); Suffix active = new Suffix(tree.root, 0, -1); for (int i = 0; i < text.length(); i++) { tree.addPrefix(active, i); } return tree; }
private void addPrefix(Suffix active, int endIndex) { Node lastParentNode = null; Node parentNode; while (true) { Edge edge; parentNode = active.getOriginNode(); // Step 1 is to try and find a matching edge for the given node. // If a matching edge exists, we are done adding edges, so we break out of this big loop. if (active.isExplicit()) { edge = active.getOriginNode().findEdge(symbolAt(endIndex)); if (edge != null) { break; } } else { // implicit node, a little more complicated edge = active.getOriginNode().findEdge(symbolAt(active.getBeginIndex())); int span = active.getSpan(); if (Objects.equal(symbolAt(edge.getBeginIndex() + span + 1), symbolAt(endIndex))) { break; } parentNode = edge.splitEdge(active); } // We didn't find a matching edge, so we create a new one, add it to the tree at the parent // node position, // and insert it into the hash table. When we create a new node, it also means we need to // create // a suffix link to the new node from the last node we visited. Edge newEdge = new Edge(endIndex, text.length() - 1, parentNode); newEdge.insert(); updateSuffixNode(lastParentNode, parentNode); lastParentNode = parentNode; // This final step is where we move to the next smaller suffix if (active.getOriginNode() == root) { active.incBeginIndex(); } else { active.changeOriginNode(); } active.canonize(); } updateSuffixNode(lastParentNode, parentNode); active.incEndIndex(); // Now the endpoint is the next active point active.canonize(); }
/** * Appends a subsequence of the specified text. If the specified character sequence is <code>null * </code> this method is equivalent to <code>append("null")</code>. * * @param txt the text to append or <code>null</code>. * @param start the index of the first character to append. * @param end the index after the last character to append. * @return <code>this</code> * @throws IndexOutOfBoundsException if <code>(start < 0) || (end < 0) * || (start > end) || (end > txt.length())</code> */ public final TextBuilder append(Text txt, int start, int end) { if (txt == null) return append("null"); if ((start < 0) || (end < 0) || (start > end) || (end > txt.length())) throw new IndexOutOfBoundsException(); int newLength = _length + end - start; while (_capacity < newLength) { increaseCapacity(); } for (int i = start, j = _length; i < end; ) { char[] chars = _high[j >> B1]; int dstBegin = j & M1; int inc = MathLib.min(C1 - dstBegin, end - i); txt.getChars(i, (i += inc), chars, dstBegin); j += inc; } _length = newLength; return this; }
/** * Appends the specified text to this text builder. If the specified text is <code>null</code> * this method is equivalent to <code>append("null")</code>. * * @param txt the text to append or <code>null</code>. * @return <code>this</code> */ public final TextBuilder append(Text txt) { return (txt == null) ? append("null") : append(txt, 0, txt.length()); }