如果您使用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]
你熟悉的任何圖形算法?圖搜索/連接算法在這裏很有用。 – djechlin
您的算法如下所示:在DFA中查找開始和接受狀態之間的所有路徑? –
@djechlin我不是,但如果你能詳細說明一個特定的算法,可以幫助我,我會很高興 –