All Downloads are FREE. Search and download functionalities are using the official Maven repository.

eu.interedition.collatex.suffixtree.ActivePoint Maven / Gradle / Ivy

package eu.interedition.collatex.suffixtree;

/**
 * Represents the Active Point used in Ukonnen's algorithm. This consists of the
 * triple active node, active edge and active length, which is used to identify
 * the point at which the next insertion should be considered.
 *
 * @param 
 * @author Max Garfinkel
 */
class ActivePoint> {

    private Node activeNode;
    private Edge activeEdge;
    private int activeLength;
    private final Node root;

    /**
     * Initialize the active point to the root of a suffix tree. This sets the
     * active point to {root,null,0}
     *
     * @param root
     */
    ActivePoint(Node root) {
        activeNode = root;
        activeEdge = null;
        activeLength = 0;
        this.root = root;
    }

    /**
     * Sets the active point to a new node, edge, length tripple.
     *
     * @param node
     * @param edge
     * @param length
     */
    void setPosition(Node node, Edge edge, int length) {
        activeNode = node;
        activeEdge = edge;
        activeLength = length;
    }

    /**
     * Sets the active edge.
     *
     * @param edge The edge to which we set the active edge.
     */
    void setEdge(Edge edge) {
        activeEdge = edge;
    }

    /**
     * Increments the active length.
     */
    void incrementLength() {
        activeLength++;
        resetActivePointToTerminal();
    }

    /**
     * Decrements the active length.
     */
    void decrementLength() {
        if (activeLength > 0)
            activeLength--;
        resetActivePointToTerminal();
    }

    /**
     * @return True if the active point is the root node. False if not.
     */
    boolean isRootNode() {
        return activeNode.equals(root) && activeEdge == null
            && activeLength == 0;
    }

    /**
     * @return True if active point is on a node. False if not.
     */
    boolean isNode() {
        return activeEdge == null && activeLength == 0;
    }

    /**
     * Retrieves the active node.
     *
     * @return The active node.
     */
    Node getNode() {
        return activeNode;
    }

    /**
     * @return True if the active point is on an edge. False if not.
     */
    boolean isEdge() {
        return activeEdge != null;
    }

    /**
     * Retrieves the current active edge.
     *
     * @return The active edge.
     */
    Edge getEdge() {
        return activeEdge;
    }

    /**
     * Retrieves the current active length.
     *
     * @return The active length.
     */
    int getLength() {
        return activeLength;
    }

    /**
     * Resets the active point after an insert.
     *
     * @param suffix The remaining suffix to be inserted.
     */
    public void updateAfterInsert(Suffix suffix) {
        if (activeNode == root && suffix.isEmpty()) {
            activeNode = root;
            activeEdge = null;
            activeLength = 0;
        } else if (activeNode == root) {
            Object item = suffix.getStart();
            activeEdge = root.getEdgeStarting(item);
            decrementLength();
            fixActiveEdgeAfterSuffixLink(suffix);
            if (activeLength == 0)
                activeEdge = null;
        } else if (activeNode.hasSuffixLink()) {
            activeNode = activeNode.getSuffixLink();
            findTrueActiveEdge();
            fixActiveEdgeAfterSuffixLink(suffix);
            if (activeLength == 0)
                activeEdge = null;
        } else {
            activeNode = root;
            findTrueActiveEdge();
            fixActiveEdgeAfterSuffixLink(suffix);
            if (activeLength == 0)
                activeEdge = null;
        }
    }

    /**
     * Deal with the case when we follow a suffix link but the active length is
     * greater than the new active edge length. In this situation we must walk
     * down the tree updating the entire active point.
     */
    private void fixActiveEdgeAfterSuffixLink(Suffix suffix) {
        while (activeEdge != null && activeLength > activeEdge.getLength()) {
            activeLength = activeLength - activeEdge.getLength();
            activeNode = activeEdge.getTerminal();
            Object item = suffix.getItemXFromEnd(activeLength + 1);
            activeEdge = activeNode.getEdgeStarting(item);
        }
        resetActivePointToTerminal();
    }

    /**
     * Finds the edge instance who's start item matches the current active edge
     * start item but comes from the current active node.
     */
    private void findTrueActiveEdge() {
        if (activeEdge != null) {
            Object item = activeEdge.getStartItem();
            activeEdge = activeNode.getEdgeStarting(item);
        }
    }

    /**
     * Resizes the active length in the case where we are sitting on a terminal.
     *
     * @return true if reset occurs false otherwise.
     */
    private boolean resetActivePointToTerminal() {
        if (activeEdge != null && activeEdge.getLength() == activeLength
            && activeEdge.isTerminating()) {
            activeNode = activeEdge.getTerminal();
            activeEdge = null;
            activeLength = 0;
            return true;
        } else {
            return false;
        }
    }

    @Override
    public String toString() {
        return "{" + activeNode.toString() + ", " + activeEdge + ", "
            + activeLength + "}";
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy