Partition refinement
In the design of algorithms, partition refinement is a technique for representing a partition of a set as a data structure that allows the partition to be refined by splitting its sets into a larger number of smaller sets. In that sense it is dual to the union-find data structure, which also maintains a partition into disjoint sets but in which the operations merge pairs of sets. In some applications of partition refinement, such as lexicographic breadth-first search, the data structure maintains as well an ordering on the sets in the partition. Partition refinement forms a  key component of several efficient algorithms on graphs and finite automata, including DFA minimization, the Coffman–Graham algorithm for parallel scheduling, and lexicographic breadth-first search of graphs. Data structure. A partition refinement algorithm maintains a family of disjoint sets . At the start of the algorithm, this family contains a single set of all the elements in the data structure. At each step of the algorithm, a set is presented to the algorithm, and each set in the family that contains members of is split into two sets, the intersection and the difference . Such an algorithm may be implemented efficiently  by maintaining data structures representing the following information: To perform a refinement operation, the algorithm loops through the elements of the given set . For each such element , it finds the set that contains , and checks whether a second set for has already been started. If not, it creates the second set and adds to a list of the sets that are split by the operation. Then, regardless of whether a new set was formed, the algorithm removes from and adds it to . In the representation in which all elements are stored in a single array, moving from one set to  another may be performed by swapping with the final element of and then decrementing the end index of and the start index of the new set. Finally, after all elements of have been processed in this way, the algorithm loops through , separating each current set from the second set that has been split from it, and reports both of these sets as being newly formed by the refinement operation. The time to perform a single refinement operations in this way is , independent of the number of elements in the family of sets and also independent of the total number of  sets in the data structure. Thus, the time for a sequence of refinements is proportional to the total size of the sets given to the algorithm in each refinement step. Applications. An early application of partition refinement was in an algorithm by for DFA minimization. In this problem, one is given as input a deterministic finite automaton, and must find an equivalent automaton with as few states as possible. Hopcroft's algorithm maintains a partition of the states of the input automaton into subsets, with the property that any two states in different subsets must be mapped to different states  of the output automaton. Initially, there are two subsets, one containing all the accepting states of the automaton and one containing the remaining states. At each step one of the subsets and one of the input symbols of the automaton are chosen, and the subsets of states are refined into states for which a transition labeled would lead to , and states for which an -transition would lead somewhere else. When a set that has already been chosen is split by a refinement, only one of the two resulting sets (the smaller of the two) needs to be chosen again; in  this way, each state participates in the sets for refinement steps and the overall algorithm takes time , where is the number of initial states and is the size of the alphabet. Partition refinement was applied by in an efficient implementation of the Coffman–Graham algorithm for parallel scheduling. Sethi showed that it could be used to construct a lexicographically ordered topological sort of a given directed acyclic graph in linear time; this lexicographic topological ordering is one of the key steps of the Coffman–Graham algorithm. In this application, the elements of the disjoint sets are vertices of the input  graph and the sets used to refine the partition are sets of neighbors of vertices. Since the total number of neighbors of all vertices is just the number of edges in the graph, the algorithm takes time linear in the number of edges, its input size. Partition refinement also forms a key step in lexicographic breadth-first search, a graph search algorithm with applications in the recognition of chordal graphs and several other important classes of graphs. Again, the disjoint set elements are vertices and the set represent sets of neighbors, so the algorithm takes linear time. Partition refinement In