#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吧 先來看看一會會涉及到操作 以下為演算法 看完演算法可能還是有些懵逼,我們一起來過一遍例項。以下圖為例。先構建乙個這樣的 然...