如果您使用 BFS,则周期无关紧要。这个想法是定义包含当前状态和指向前驱节点的指针的搜索节点。因此,当您访问一个接受状态的节点时,您可以向后跟踪先前的指针以确定接受的字符串(反向)。事实证明,如果搜索节点还包含导致从前一个节点状态转换到当前节点状态的字符,那么它是优雅的。
这是 Java 中的一种方法:
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
class Experimental {
// DFA state with its transitions, possibly accepting.
static class State {
final Map<Character, State> transitions = new HashMap<>();
final boolean accept;
State(boolean accept) {
this.accept = accept;
}
}
// A little DFA.
static final State s0 = new State(false);
static final State s1 = new State(false);
static final State s2 = new State(true);
static final State s3 = new State(true);
static {
s0.transitions.put('a', s1);
s0.transitions.put('b', s2);
s0.transitions.put('c', s3);
s1.transitions.put('d', s3);
s2.transitions.put('e', s0);
s2.transitions.put('f', s1);
}
// An enumerator of strings accepted by the DFA in order of length.
static class Enumerator {
static class Node {
final Node prev;
final char prevCh;
final State state;
Node(State start) {
this(null, Character.MIN_VALUE, start);
}
Node(Node prev, char ch, State state) {
this.prev = prev;
this.prevCh = ch;
this.state = state;
}
}
final Deque<Node> queue = new ArrayDeque<>();
final List<String> output = new ArrayList<>();
final State start;
Enumerator(State start) {
this.start = start;
}
Enumerator enumerate(int outputLimit) {
queue.clear();
output.clear();
// Enqueue a search node for the start state.
queue.add(new Node(start));
while (!queue.isEmpty() && output.size() < outputLimit) {
Node current = queue.pollFirst();
if (current.state.accept) {
// Follow prev pointers to build the accepted string.
StringBuilder sb = new StringBuilder();
for (Node p = current; p.prev != null; p = p.prev) {
sb.append(p.prevCh);
}
output.add(sb.reverse().toString());
}
// Enqueue nodes for the successors of current state.
for (Entry<Character, State> transition : current.state.transitions.entrySet()) {
queue.addLast(new Node(current, transition.getKey(), transition.getValue()));
}
}
return this;
}
}
public static void main(String[] args) {
System.out.println(new Enumerator(s0).enumerate(20).output);
}
}
输出:
[b, c, ad, beb, bec, bfd, bead, bebeb, bebec, bebfd, bebead, bebebeb, bebebec, bebebfd, bebebead, bebebebeb, bebebebec, bebebebfd, bebebebead, bebebebebeb]