如何將 不確定的有窮自動機(NFA) 轉化為 確定的有窮自動機(DFA) 並將DFA最簡化


一、從NFA到DFA的轉換

例如下圖:

 

DFA的每個狀態都是一個由NFA中的狀態構成的集合,即NFA狀態集合的一個子集

 

r =aa*bb*cc*

 

二、從帶有ε-邊的NFA到DFA的轉換

r=0*1*2*

三、子集構造法( subset construction)

 輸入:NFA N
 輸出:接收同樣語言的DFA D
 方法:一開始,ε-closure ( s0 )是Dstates 中的唯一狀態,且它未加標記;

while(在Dstates中有一個未標記狀態T ) { 給T加上標記; for(每個輸入符號a) { U = ε-closure(move(T, a)); if ( U不在Dstates中) 將U加入到Dstates中,且不加標記; Dtran[T, a]=U ; } } 

四、計算 ε-closure (T )

將T的所有狀態壓入stack中;將ε-closure  (T )初始化為 T ;

 while(stack非空) {   將棧頂元素 t 給彈出棧中;   for(每個滿足如下條件的u :從t出發有一個標號為ε的轉換到達狀態u)     if ( u不在ε-closure (T )中)     {       將u加入到ε-closure (T )中;將u壓入棧中;     } }

接下來我們結合一個例題來具體實踐一下根據正規文法構造NFA,接着確定化NFA,最后化簡DFA

例:例題:為正規文法G[S]

       S→aA|bQ

       A→aA|bB|b

       B→bD|aQ

       Q→aQ|bD|b

       D→bB|aA

       E→aB|bF

       F→bD|aE|b

  構造相應的DFA。 

 

答:

 

首先消除無用符號及其所在的產生式:
觀察題目我們可以發現,E不出現在任何產生式的右部,所以E是無效符號,
刪除E所在的產生式之后,符號F也不出現在任何產生式的右部,則F是無效符號,
刪除F及其所在產生式。此時除了文法開始符號S之外,其余非終結符都是從S可達的。
 
接着便只需要為正規文法G[S]
       S→aA|bQ
       A→aA|bB|b
       B→bD|aQ
       Q→aQ|bD|b
       D→bB|aA
  構造相應的最簡DFA。 
 
接着我們根據珍貴文法構造出下圖的NFA:
 

接下來我們將NFA進行確定化,新增一個狀態T表示終止態:

構建下圖的子集表,最開始只有起始態:

根據上圖NFA,可得下圖:

出現了兩個新增狀態子集{ A }{ Q},我們把它加入到狀態集中:

根據NFA可得出下表:

出現了兩個新增狀態子集{ B,T}{ D,T}(紅色背景),而{ A }{ Q}(綠色背景)已經存在與狀態集中,可以不做處理。(字體顏色為綠色的T表示終態),

接着我們把新增的狀態子集{ B,T}{ D,T}添加到狀態集之中:

有NFA可得下表,可以根據上述方法看出,出現了新增狀態子集{ B}{ D}(紅色背景),而{ A }{ Q}(綠色背景)已經存在與狀態集中,可以不做處理。

接着我們把新增的狀態子集{ B}{ D}添加到狀態集之中

 

有NFA得出下表,發現已經沒有新增的狀態子集了:

zhe這時候便可以重命名狀態集,其中包含終態(綠色狀態T)的子集相應的變成終態:

根據這個狀態集表,我們構造DFA:

此時已經完成了NFA轉化為DFA的過程,最后我們將DFA進行化簡,這里采用的方法是“划分法”

首先我們將這留個狀態划分為非終態集 { 0,1,2,5,6 }; 終態集 { 3,4 };

同樣的我們首先將DFA的表簡單直觀的構造出來:

 

根據上表,可以得出如下圖,

 

當非終態子集{ 0,1,2,5,6 }遇到a時,所得子集為{1,2},包含於{ 0,1,2,5,6 },暫時可以不用再分,轉去考慮遇到b時的情況:

 

 

我們可以看到,經由b所得到的子集,不包含於任何一個已存在的子集,所以此時需要對非終態集 { 0,1,2,5,6 }進行划分,我們可以觀察如下圖:

 

其中0,5,6三個狀態經由b所得的子集是包含於已存在的子集{ 0,1,2,5,6 }中的,而狀態1,2經由b所得的子集也是包含於已存在的子集{ 3 , 4}中的,所以我們再次划分為{0,5,6},{1,2}, { 3,4 }

 

這時候首先我們討論子集{0,5,6}根據DFA表我們可以做出下表,經由a時的結果{1,2}包含於已存在子集:

 

子集{0,5,6}根據DFA表,經由b時的結果{2,5,6}不包含於任何一個已存在子集:

 

觀察下圖:

 

我們發現需要將狀態5,6再次分為一個子集,0單獨分一個子集。得到新的已存在狀態集:

 

首先討論子集{3,4},遇到a,b的情況,如下圖;

所以此時子集{3,4}不需要再分。

 

 再討論子集{1,2},遇到a,b的情況,如下圖;

所以此時子集{1,2}也不需要再分。

 

再討論子集{5,6},遇到a,b的情況,如下圖;

所以此時子集{5,6}也不需要再分.

 

此時令狀態3代表{3,4}(同時也是終態集),把原來到達狀態4的弧都導入3,並刪除狀態4;

狀態1代表{1,2},把原來到達狀態2的弧都導入1,並刪除狀態2;

狀態5代表{5,6},把原來到達狀態6的弧都導入5,並刪除狀態6;

 

便得到了化簡后的DFA:

 

結束

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM