/** * Removes a String from the MDAG. * * @param str the String to be removed from the MDAG */ public void removeString(String str) { if (sourceNode != null) { // Split the _transition path corresponding to str to ensure that // any other _transition paths sharing nodes with it are not affected splitTransitionPath(sourceNode, str); // Remove from equivalenceClassMDAGNodeHashMap, the entries of all the nodes in the // _transition path corresponding to str. removeTransitionPathRegisterEntries(str); // Get the last node in the _transition path corresponding to str MDAGNode strEndNode = sourceNode.transition(str); if (strEndNode == null) return; if (!strEndNode.hasTransitions()) { int soleInternalTransitionPathLength = calculateSoleTransitionPathLength(str); int internalTransitionPathLength = str.length() - 1; if (soleInternalTransitionPathLength == internalTransitionPathLength) { sourceNode.removeOutgoingTransition(str.charAt(0)); transitionCount -= str.length(); } else { // Remove the sub-path in str's _transition path that is only used by str int toBeRemovedTransitionLabelCharIndex = (internalTransitionPathLength - soleInternalTransitionPathLength); MDAGNode latestNonSoloTransitionPathNode = sourceNode.transition(str.substring(0, toBeRemovedTransitionLabelCharIndex)); latestNonSoloTransitionPathNode.removeOutgoingTransition( str.charAt(toBeRemovedTransitionLabelCharIndex)); transitionCount -= str.substring(toBeRemovedTransitionLabelCharIndex).length(); ///// replaceOrRegister(sourceNode, str.substring(0, toBeRemovedTransitionLabelCharIndex)); } } else { strEndNode.setAcceptStateStatus(false); replaceOrRegister(sourceNode, str); } } else { unSimplify(); } }
/** * 在从给定节点开始的一段路径上执行最小化<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); } }