從正則表達式到 NFA 到 DFA 到最簡 DFA (二)
NFA $ \rightarrow $ DFA (子集構造法)
這里我們用一個例子來解釋。
如上圖所示,這是上一篇文章中的正則表達式化成的 NFA,這里拿來接着用。
我們首先看開始狀態 n0。n0 在接收了一個字符 a 之后可以轉換到 n1,這個時候我們要看 n1 是否存在 $ \varepsilon $ 轉移。若存在,則遞歸的將所有能 $ \varepsilon $ 轉移的狀態添加到一個集合里(包括 n1)。然后再看我們所創造的這個集合是否可以接收字符,接收字符后轉移到的狀態是否還有 $ \varepsilon $ 轉移,依此類推。
拿這個圖舉例子就是:
$ n0 \xrightarrow{a} n1 $
n1 能 $ \varepsilon $ 轉換到的狀態是 q1,即 \(\{ n1, n2, n3, n4, n6, n9 \} : q1\) ,記 \(\{n0\}: q0\)
$ q1 \xrightarrow{b} n5 $
n5 能 $ \varepsilon $ 轉移到的狀態是 q2,即 \(\{ n5, n8, n9, n3, n4, n6 \} : q2\)
\(q2 \xrightarrow{...} \{...\} : q3\)
我們構造的這個集合就叫做 $ \varepsilon - $閉包。
工作表算法
q0 ← Ɛ-閉包(n0)
Q ← {q0}
workList ← q0
while (workList != [])
remove q from workList
foreach char c
t ← Ɛ-閉包(delta(q, c))
D[q, c] ← t
if t 不屬於 Q
add t to Q and workList
最終,Q 中的所有集合就是我們要求的 DFA 中的每個狀態。再將狀態轉移連好,轉換后的 DFA 就形成了。