NFA到DFA的轉換

2021-07-03 17:30:27 字數 3615 閱讀 4656

#include

#include

#include

#include

#include

#include

#define max 100

using

namespace

std;

struct edge

;struct newj //得到的狀態集合

;struct relation //集合和集合之間的轉換聯絡

;void geteclosure(const edge *e, int cntedge, newj *st) //得到閉包}}

}void move(char ttchar, edge *e, int cntedge, newj *source, newj *dest) //e為所有邊的集合,然後就能從乙個轉換字元得到全部的,比如2得到bd,而不會第乙個2得到b,第二個2得到d}}

}//通過狀態集合中的setj來決定是否新增

bool isinsert(vector

allset, newj *newset)

return b;

}//判斷relation結構體去重

bool isinsertforrel(vector

relvec, newj* prej, char jchar, newj* nextj)

return isin;

}void uniquechars(char*arr, int n, char *outs)

}//重新命名轉換

void changename(vector

allset, newj *tj, string& newstr)

newstr = tmpj->setj;

}int main()

; //不為空字元的邊陣列

cout

<< "輸入各邊的資訊,並且以 '前點(char 'a'-'z') 轉換字元(char '1'-'9') 後點(char 'a'-'z')'格式,結束以'$'開頭"

<< endl;

cout

<< "如果轉換字元為空,則用'0'表示"

<< endl;

//以 prenode tchar nextnpde來進行邊的輸入。並且以 '$'結束輸入

for (int i = 0; i < max; i++)

//將edge邊的結點放入向量中

for (int i = 0; i < cntedge; i++)

cout

<< "輸入初始點字元"

<< endl;

cin >> stanode;

while (node.find(stanode) == string::npos)

cout

<< "輸入終止點字元(若有多個終結狀態,直接寫成字串形式)"

<< endl;

cin >> endnode;

bool inputstatus = true;

while (inputstatus)

}inputstatus = false;

}newj *newset = new newj();

newset->setj = stanode; //設定初始點為狀態集合i

geteclosure(e, cntedge, newset); //

vector

allset(1, newset); //設定所有狀態集合的向量

vector

::iterator iter;

int sizeofstrvec = 1;

/*用來儲存每一次的閉包操作前的第一列的狀態集合

*比如第一次strvec儲存的是初始狀態,求閉包時多了2個狀態集合。在第二次時儲存的是新的2個狀態,原先的初始狀態被去除。

*總的狀態集合儲存在allset中

*/vector

strvec(1, newset);

vector

relvec;

while (sizeofstrvec) //如果不符合則說明新增的集合都是原有的集合

//在新增relvec時,只要是不為空就要新增,這裡會使reldest的元素可能重複(當乙個字元出現在多條邊中)

if (dest->setj != "")}}

}}strvec.clear();

int newallset = allset.size();

for (int i = oldallset; i < allset.size(); i++) //將allset中新增的後面元素新增進strvec中。

sizeofstrvec = strvec.size();

}cout

<< "轉換結果"

<< endl;

vector

::iterator reliter;

for (reliter = relvec.begin(); reliter != relvec.end(); reliter++)

char upperchars[26];

memset(upperchars, 0, sizeof(char) * 26);

cout

<< "重新命名如下:"

<< endl;

for (int i = 0; i < allset.size(); i++)

vector

newrelvec; //經過重新命名後的relvec

for (int i = 0; i < relvec.size(); i++)

//輸出驗證重新命名的集合關係

cout

<< "最終轉換:"

<< endl;

vector

::iterator newreliter;

for (newreliter = newrelvec.begin(); newreliter != newrelvec.end(); newreliter++)

//得出初始狀態和接受狀態

cout

<< "接受狀態是:"

<< endl;

int outsize = allset.size();

char *output = new

char[outsize];

memset(output, 0, sizeof(char)*outsize);

int outputcnt = 0;

for (int k = 0; k < allset.size(); k++)

}//陣列去重輸出

**都有比較詳細的注釋,經過測試可以適合任何形式的nfa到dfa的轉換。

NFA到DFA的轉換

又稱nfa的確定化 狀態轉換表 注 標有 為接收狀態 帶 邊記得增加一列 nfa的開始狀態集合為 0 將nfa將接收的符號代入當前狀態,最長子串原則,得出新產生的狀態 將新產生的狀態作為將來要列出的狀態重複1中步驟 直至新產生的狀態集合中無新集合時結束 將第一列中將來要列的狀態重新命名 轉換為dfa...

NFA到DFA的轉換演示

複習一下編譯,在龍書中提到的nfa 不確定有窮自動機 到dfa 確定有窮自動機 的轉換,master regular expression中提到的不依賴於正規表示式的識別問題,不用精心構造正規表示式,只需將正規表示式轉化為nfa,進而轉化為dfa,則任何長度為n的字串都可以在o n 時間內判斷出來是...

NFA到DFA的轉換及DFA的簡化

確定型有窮自動機是不確定有窮自動機中的乙個特例,其中 沒有輸出 之上的轉換動作。對每個狀態s和每個輸入符號a,有且只有一條標號為a的邊離開s 下面來看看nfa怎麼轉換為dfa吧 先來看看一會會涉及到操作 以下為演算法 看完演算法可能還是有些懵逼,我們一起來過一遍例項。以下圖為例。先構建乙個這樣的 然...