Пример #1
0
  /**
   * 从给点节点开始克隆一条路径<br>
   * Clones a _transition path from a given node.
   *
   * @param pivotConfluenceNode the MDAGNode that the cloning operation is to be based from
   * @param transitionStringToPivotNode a String which corresponds with a _transition path from
   *     souceNode to {@code pivotConfluenceNode}
   * @param str a String which corresponds to the _transition path from {@code pivotConfluenceNode}
   *     that is to be cloned
   */
  private void cloneTransitionPath(
      MDAGNode pivotConfluenceNode, String transitionStringToPivotNode, String str) {
    MDAGNode lastTargetNode =
        pivotConfluenceNode.transition(
            str); // Will store the last node which was used as the base of a cloning operation
    MDAGNode lastClonedNode = null; // Will store the last cloned node
    char lastTransitionLabelChar =
        '\0'; // Will store the char which labels the _transition to lastTargetNode from its parent
              // node in the prefixString's _transition path

    // Loop backwards through the indices of str, using each as a boundary to create substrings of
    // str of decreasing length
    // which will be used to _transition to, and duplicate the nodes in the _transition path of str
    // from pivotConfluenceNode.
    for (int i = str.length(); i >= 0; i--) {
      String currentTransitionString = (i > 0 ? str.substring(0, i) : null);
      MDAGNode currentTargetNode =
          (i > 0 ? pivotConfluenceNode.transition(currentTransitionString) : pivotConfluenceNode);
      MDAGNode clonedNode;

      if (i == 0) // if we have reached pivotConfluenceNode
      {
        // Clone pivotConfluenceNode in a way that reassigns the _transition of its parent node (in
        // transitionStringToConfluenceNode's path) to the clone.
        String transitionStringToPivotNodeParent =
            transitionStringToPivotNode.substring(0, transitionStringToPivotNode.length() - 1);
        char parentTransitionLabelChar =
            transitionStringToPivotNode.charAt(transitionStringToPivotNode.length() - 1);
        clonedNode =
            pivotConfluenceNode.clone(
                sourceNode.transition(transitionStringToPivotNodeParent),
                parentTransitionLabelChar);
        /////
      } else clonedNode = currentTargetNode.clone(); // simply clone curentTargetNode

      transitionCount += clonedNode.getOutgoingTransitionCount();

      // If this isn't the first node we've cloned, reassign clonedNode's _transition labeled
      // with the lastTransitionChar (which points to the last targetNode) to the last clone.
      if (lastClonedNode != null) {
        clonedNode.reassignOutgoingTransition(
            lastTransitionLabelChar, lastTargetNode, lastClonedNode);
        lastTargetNode = currentTargetNode;
      }

      // Store clonedNode and the char which labels the _transition between the node it was cloned
      // from (currentTargetNode) and THAT node's parent.
      // These will be used to establish an equivalent _transition to clonedNode from the next clone
      // to be created (it's clone parent).
      lastClonedNode = clonedNode;
      lastTransitionLabelChar = (i > 0 ? str.charAt(i - 1) : '\0');
      /////
    }
    /////
  }
Пример #2
0
  /**
   * Creates a SimpleMDAGNode version of an MDAGNode's outgoing _transition set in mdagDataArray.
   *
   * @param node the MDAGNode containing the _transition set to be inserted in to {@code
   *     mdagDataArray}
   * @param mdagDataArray an array of SimpleMDAGNodes containing a subset of the data of the MDAG
   * @param onePastLastCreatedTransitionSetIndex an int of the index in {@code mdagDataArray} that
   *     the outgoing _transition set of {@code node} is to start from
   * @return an int of one past the end of the _transition set located farthest in {@code
   *     mdagDataArray}
   */
  private int createSimpleMDAGTransitionSet(
      MDAGNode node, SimpleMDAGNode[] mdagDataArray, int onePastLastCreatedTransitionSetIndex) {
    int pivotIndex = onePastLastCreatedTransitionSetIndex; // node自己的位置
    node.setTransitionSetBeginIndex(pivotIndex);

    onePastLastCreatedTransitionSetIndex += node.getOutgoingTransitionCount(); // 这个参数代表id的消耗

    // Create a SimpleMDAGNode representing each _transition label/target combo in
    // transitionTreeMap, recursively calling this method (if necessary)
    // to set indices in these SimpleMDAGNodes that the set of transitions emitting from their
    // respective _transition targets starts from.
    TreeMap<Character, MDAGNode> transitionTreeMap = node.getOutgoingTransitions();
    for (Entry<Character, MDAGNode> transitionKeyValuePair : transitionTreeMap.entrySet()) {
      // Use the current _transition's label and target node to create a SimpleMDAGNode
      // (which is a space-saving representation of the _transition), and insert it in to
      // mdagDataArray
      char transitionLabelChar = transitionKeyValuePair.getKey();
      MDAGNode transitionTargetNode = transitionKeyValuePair.getValue();
      mdagDataArray[pivotIndex] =
          new SimpleMDAGNode(
              transitionLabelChar,
              transitionTargetNode.isAcceptNode(),
              transitionTargetNode.getOutgoingTransitionCount());
      /////

      // If targetTransitionNode's outgoing _transition set hasn't been inserted in to mdagDataArray
      // yet, call this method on it to do so.
      // After this call returns, transitionTargetNode will contain the index in mdagDataArray that
      // its _transition set starts from
      if (transitionTargetNode.getTransitionSetBeginIndex() == -1)
        onePastLastCreatedTransitionSetIndex =
            createSimpleMDAGTransitionSet(
                transitionTargetNode, mdagDataArray, onePastLastCreatedTransitionSetIndex);

      mdagDataArray[pivotIndex++].setTransitionSetBeginIndex(
          transitionTargetNode.getTransitionSetBeginIndex());
    }
    /////

    return onePastLastCreatedTransitionSetIndex;
  }
Пример #3
0
  /**
   * 固化自己<br>
   * Creates a space-saving version of the MDAG in the form of an array. Once the MDAG is
   * simplified, Strings can no longer be added to or removed from it.
   */
  public void simplify() {
    if (sourceNode != null) {
      mdagDataArray = new SimpleMDAGNode[transitionCount];
      createSimpleMDAGTransitionSet(sourceNode, mdagDataArray, 0);
      simplifiedSourceNode =
          new SimpleMDAGNode('\0', false, sourceNode.getOutgoingTransitionCount());

      // Mark the previous MDAG data structure and equivalenceClassMDAGNodeHashMap
      // for garbage collection since they are no longer needed.
      sourceNode = null;
      equivalenceClassMDAGNodeHashMap = null;
      /////
    }
  }
Пример #4
0
  /**
   * 在从给定节点开始的一段路径上执行最小化<br>
   * Performs minimization processing on a _transition path starting from a given node.
   *
   * <p>This entails either replacing a node in the path with one that has an equivalent right
   * language/equivalence class (defined as set of _transition paths that can be traversed and nodes
   * able to be reached from it), or making it a representative of a right language/equivalence
   * class if a such a node does not already exist.
   *
   * @param originNode the MDAGNode that the _transition path corresponding to str starts from
   * @param str a String related to a _transition path
   */
  private void replaceOrRegister(MDAGNode originNode, String str) {
    char transitionLabelChar = str.charAt(0);
    MDAGNode relevantTargetNode = originNode.transition(transitionLabelChar);

    // If relevantTargetNode has transitions and there is at least one char left to process,
    // recursively call
    // this on the next char in order to further processing down the _transition path corresponding
    // to str
    if (relevantTargetNode.hasTransitions() && !str.substring(1).isEmpty())
      replaceOrRegister(relevantTargetNode, str.substring(1));
    /////

    // Get the node representing the equivalence class that relevantTargetNode belongs to. MDAGNodes
    // hash on the
    // transitions paths that can be traversed from them and nodes able to be reached from them;
    // nodes with the same equivalence classes will hash to the same bucket.
    MDAGNode equivalentNode = equivalenceClassMDAGNodeHashMap.get(relevantTargetNode);

    if (equivalentNode
        == null) // if there is no node with the same right language as relevantTargetNode
    equivalenceClassMDAGNodeHashMap.put(relevantTargetNode, relevantTargetNode);
    else if (equivalentNode
        != relevantTargetNode) // if there is another node with the same right language as
                               // relevantTargetNode, reassign the
    { // _transition between originNode and relevantTargetNode, to originNode and the node
      // representing the equivalence class of interest
      relevantTargetNode.decrementTargetIncomingTransitionCounts();
      transitionCount -=
          relevantTargetNode
              .getOutgoingTransitionCount(); // Since this method is recursive, the outgoing
                                             // transitions of all of relevantTargetNode's child
                                             // nodes have already been reassigned,
      // so we only need to decrement the _transition count by the relevantTargetNode's outgoing
      // _transition count
      originNode.reassignOutgoingTransition(
          transitionLabelChar, relevantTargetNode, equivalentNode);
    }
  }
Пример #5
0
  private void splitTransitionPath(MDAGNode originNode, String storedStringSubstr) {
    HashMap<String, Object> firstConfluenceNodeDataHashMap =
        getTransitionPathFirstConfluenceNodeData(originNode, storedStringSubstr);
    Integer toFirstConfluenceNodeTransitionCharIndex =
        (Integer) firstConfluenceNodeDataHashMap.get("toConfluenceNodeTransitionCharIndex");
    MDAGNode firstConfluenceNode = (MDAGNode) firstConfluenceNodeDataHashMap.get("confluenceNode");

    if (firstConfluenceNode != null) {
      MDAGNode firstConfluenceNodeParent =
          originNode.transition(
              storedStringSubstr.substring(0, toFirstConfluenceNodeTransitionCharIndex));

      MDAGNode firstConfluenceNodeClone =
          firstConfluenceNode.clone(
              firstConfluenceNodeParent,
              storedStringSubstr.charAt(toFirstConfluenceNodeTransitionCharIndex));

      transitionCount += firstConfluenceNodeClone.getOutgoingTransitionCount();

      String unprocessedSubString =
          storedStringSubstr.substring(toFirstConfluenceNodeTransitionCharIndex + 1);
      splitTransitionPath(firstConfluenceNodeClone, unprocessedSubString);
    }
  }