/** * Retrieves Strings corresponding to all valid _transition paths from a given node that satisfy a * given condition. * * @param strHashSet a HashSet of Strings to contain all those in the MDAG satisfying {@code * searchCondition} with {@code conditionString} * @param searchCondition the SearchCondition enum field describing the type of relationship that * Strings contained in the MDAG must have with {@code conditionString} in order to be * included in the result set * @param searchConditionString the String that all Strings in the MDAG must be related with in * the fashion denoted by {@code searchCondition} in order to be included in the result set * @param prefixString the String corresponding to the currently traversed _transition path * @param transitionTreeMap a TreeMap of Characters to MDAGNodes collectively representing an * MDAGNode's _transition set */ private void getStrings( HashSet<String> strHashSet, SearchCondition searchCondition, String searchConditionString, String prefixString, TreeMap<Character, MDAGNode> transitionTreeMap) { // Traverse all the valid _transition paths beginning from each _transition in // transitionTreeMap, inserting the // corresponding Strings in to strHashSet that have the relationship with conditionString // denoted by searchCondition for (Entry<Character, MDAGNode> transitionKeyValuePair : transitionTreeMap.entrySet()) { String newPrefixString = prefixString + transitionKeyValuePair.getKey(); MDAGNode currentNode = transitionKeyValuePair.getValue(); if (currentNode.isAcceptNode() && searchCondition.satisfiesCondition(newPrefixString, searchConditionString)) strHashSet.add(newPrefixString); // Recursively call this to traverse all the valid _transition paths from currentNode getStrings( strHashSet, searchCondition, searchConditionString, newPrefixString, currentNode.getOutgoingTransitions()); } ///// }
/** * 是否包含<br> * Determines whether a String is present in the MDAG. * * @param str the String to be searched for * @return true if {@code str} is present in the MDAG, and false otherwise */ public boolean contains(String str) { if (sourceNode != null) // if the MDAG hasn't been simplified { MDAGNode targetNode = sourceNode.transition(str.toCharArray()); return (targetNode != null && targetNode.isAcceptNode()); } else { SimpleMDAGNode targetNode = simplifiedSourceNode.transition(mdagDataArray, str.toCharArray()); return (targetNode != null && targetNode.isAcceptNode()); } }
/** * 前缀查询<br> * Retrieves all the Strings in the MDAG that begin with a given String. * * @param prefixStr a String that is the prefix for all the desired Strings * @return a HashSet containing all the Strings present in the MDAG that begin with {@code * prefixString} */ public HashSet<String> getStringsStartingWith(String prefixStr) { HashSet<String> strHashSet = new HashSet<String>(); if (sourceNode != null) // if the MDAG hasn't been simplified { MDAGNode originNode = sourceNode.transition( prefixStr); // attempt to _transition down the path denoted by prefixStr if (originNode != null) // if there a _transition path corresponding to prefixString (one or more stored // Strings begin with prefixString) { if (originNode.isAcceptNode()) strHashSet.add(prefixStr); getStrings( strHashSet, SearchCondition.PREFIX_SEARCH_CONDITION, prefixStr, prefixStr, originNode .getOutgoingTransitions()); // retrieve all Strings that extend the _transition path // denoted by prefixStr } } else { SimpleMDAGNode originNode = SimpleMDAGNode.traverseMDAG( mdagDataArray, simplifiedSourceNode, prefixStr); // attempt to _transition down the path denoted by prefixStr if (originNode != null) // if there a _transition path corresponding to prefixString (one or more stored // Strings begin with prefixStr) { if (originNode.isAcceptNode()) strHashSet.add(prefixStr); getStrings( strHashSet, SearchCondition.PREFIX_SEARCH_CONDITION, prefixStr, prefixStr, originNode); // retrieve all Strings that extend the _transition path denoted by // prefixString } } return strHashSet; }
/** * 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; }
/** * Calculates the length of the the sub-path in a _transition path, that is used only by a given * string. * * @param str a String corresponding to a _transition path from sourceNode * @return an int denoting the size of the sub-path in the _transition path corresponding to * {@code str} that is only used by {@code str} */ private int calculateSoleTransitionPathLength(String str) { Stack<MDAGNode> transitionPathNodeStack = sourceNode.getTransitionPathNodes(str); transitionPathNodeStack.pop(); // The MDAGNode at the top of the stack is not needed // (we are processing the outgoing transitions of nodes inside str's _transition path, // the outgoing transitions of the MDAGNode at the top of the stack are outside this path) transitionPathNodeStack.trimToSize(); // Process each node in transitionPathNodeStack, using each to determine whether the // _transition path corresponding to str is only used by str. This is true if and only if // each node in the _transition path has a single outgoing _transition and is not an accept // state. while (!transitionPathNodeStack.isEmpty()) { MDAGNode currentNode = transitionPathNodeStack.peek(); if (currentNode.getOutgoingTransitions().size() <= 1 && !currentNode.isAcceptNode()) transitionPathNodeStack.pop(); else break; } ///// return (transitionPathNodeStack.capacity() - transitionPathNodeStack.size()); }