#include <iostream>#include <string>#include <cstring>#include <vector>#include <algorithm>#include <set>#define MAXusing namespace STD;structedge{CharPrenode;The //node indicates that only a single character can be used CharNextNode;CharTchar//Convert characters};structNewj//Get the status set{stringSETJ;};structRelationtransitions between collections and collections{newj* Prej;CharJchar; Newj* NEXTJ;};voidGeteclosure (ConstEdge *e,intCntedge, NEWJ *st)//Get closures{ for(inti =0; I < st->setj.length (); i++)//Take out the state in each State collection{ for(intj =0; J < Cntedge; J + +)//test each edge{if(E[j].prenode = = St->setj[i] && E[j].tchar = =' 0 ')The //conversion character is ' 0 ', which is a null character{ST->SETJ + = E[j].nextnode; } } }}voidMoveCharTtchar, Edge *e,intCntedge, Newj *source, Newj *dest)The //e is a collection of all the edges, and then can get all from a converted character, such as 2 to get BD, not the first 2 to get B, the second 2 to get D{ for(inti =0; I < source->setj.length (); i++)//Take out the state in each State collection{ for(intj =0; J < Cntedge; J + +) {if(E[j].prenode = = Source->setj[i] && E[j].tchar = = Ttchar) {DEST->SETJ + = E[j].nextnode; } } }}//By SETJ in the State collection to decide whether to addBOOLIsinsert ( vector<newJ*>Allset, Newj *newset) {BOOLb =true; for(intK =0; K < Allset.size (); k++) {if(allset.at (k)->setj = = NEWSET->SETJ) b =false; }returnb;}//Judging relation structural body de-weightBOOLIsinsertforrel ( vector<relation*>Relvec, newj* Prej,CharJchar, newj* nextj) {BOOLIsIn =true; for(inti =0; I < relvec.size (); i++) {if(relvec.at (i)->prej->setj = = Prej->setj && relvec.at (i)->NEXTJ->SETJ = NEXTJ->SETJ & & Relvec.at (i)->jchar = = Jchar) IsIn =false; }returnIsIn;}voidUniquechars (Char*arr,intNChar*outs) {memset(Outs,0,sizeof(Char) *n);CharFirst = arr[0]; for(inti =0; I < n; i++) {Outs[arr[i]-first] = Arr[i]; }}//Rename TransformationvoidChangeName ( vector<newJ*>Allset, Newj *TJ,string& newstr) {NEWJ *TMPJ =NewNEWJ (); for(inti =0; I < allset.size (); i++) {if(TJ->SETJ = = allset.at (i)->setj) TMPJ->SETJ =' A '+ i; } newstr = TMPJ->SETJ;}intMain () {edge* E =NewEdge[max];intCntedge =0;CharStanode;//Start point and end point stringEndnode;stringNode;//Node collection intCntrealedge[max] = {0};//non-null character array of edges cout<<"Enter the information for each side and convert the character (char ' a '-'-') ' in the ' preceding point (char ' a '-'-' z ') to the ' format ' of char ' a '-'-'-' 1 '-'-') ', ending with ' $ '<< Endl;cout<<"If the conversion character is empty, use ' 0 ' for"<< Endl;//Use Prenode TCHAR Nextnpde to enter the side. and end the input with ' $ ' for(inti =0; i < MAX; i++) {Cin>> E[i].prenode;if((e[i].prenode) = =' $ ') Break;Cin>> E[i].tchar >> E[i].nextnode;if(E[i].tchar = =' 0 ') Cntrealedge[cntedge] =1; cntedge++; }//Put nodes in the edge edge into vectors for(inti =0; i < Cntedge; i++) {CharPretmp = E[i].prenode;CharNexttmp = E[i].nextnode;//The nodes in the side are not included, add if(Node.find (pretmp) > Node.length ()) Node + = pretmp;if(Node.find (nexttmp) > Node.length ()) Node + = nexttmp; }cout<<"Input initial point character"<< Endl;Cin>> Stanode; while(Node.find (stanode) = =string:: NPOs) {cout<<"Initial state input Error"<< Endl;Cin>> Stanode; }cout<<"Enter the terminating point character (if there is more than one end state, write directly as a string)"<< Endl;Cin>> Endnode;BOOLInputstatus =true; while(Inputstatus) { for(inti =0; I < endnode.length (); i++) {if(Node.find (endnode[i]) = =string:: NPOs) {cout<<"End state input Error"<< Endl;cout<<"Please re-enter:"<< Endl;Cin>> Endnode; }} inputstatus =false; } NEWJ *newset =NewNEWJ (); NEWSET->SETJ = Stanode;//Set initial point as State set IGeteclosure (E, Cntedge, newset);// vector<newJ*>Allset (1, Newset);//Set vector for all state sets vector<newJ*>:: Iterator iter;intSizeofstrvec =1;/* Used to store the state set of the first column before each closure operation * For example, the first time Strvec storage is the initial state, the closure of the packet when the 2 more state sets. At the second time, the new 2 states are stored, and the original initial state is removed. * The total state collection is stored in allset */ vector<newJ*>Strvec (1, Newset); vector<relation*>Relvec; while(Sizeofstrvec)//If not compliant then the new collection is the original collection{intOldallset = Allset.size (); for(intj =0; J < Sizeofstrvec; J + +) { for(inti =0; i < Cntedge; i++)//For each letter to be similar to IK; this loop handles only one row{NEWJ *dest =NewNEWJ ();if(!cntrealedge[i])//Remove edges of empty conversion characters{Move (E[i].tchar, E, Cntedge, strvec.at (j), dest);//If there is a character on multiple edges, you want to set the same collation by character. Otherwise it will make the state set apart and cause errors!! Geteclosure (E, Cntedge, dest);//At this time dest for Ia,ib and the like. if(Isinsert (Allset, dest) && DEST->SETJ! ="")//not found and DEST->SETJ and not empty add{Allset.push_back (dest); }//When adding Relvec, as long as it is not empty to add, this will make reldest elements may be repeated (when one character appears in multiple edges) if(DEST->SETJ! ="") {relation* Reldest =NewRelation (); Reldest->prej = strvec.at (j); Reldest->jchar = E[i].tchar; RELDEST->NEXTJ = dest;BOOLIsIn = Isinsertforrel (Relvec, Reldest->prej, Reldest->jchar, RELDEST->NEXTJ);if(isIn)//de-weight{Relvec.push_back (reldest); }}}}} strvec.clear ();intNewallset = Allset.size (); for(inti = Oldallset; I < allset.size (); i++)//Add the new later elements in the Allset into the Strvec. {NEWJ *dest =NewNEWJ (); Dest = allset.at (i); Strvec.push_back (dest); } Sizeofstrvec = Strvec.size (); }cout<<"Conversion Results"<< Endl; vector<relation*>:: Iterator Reliter; for(Reliter = Relvec.begin (); Reliter! = Relvec.end (); reliter++) {cout<< (*reliter)->PREJ->SETJ <<" "<< (*reliter)->jchar <<" "<< (*reliter)->nextj->setj << Endl; }Charupperchars[ -];memset(Upperchars,0,sizeof(Char) * -);cout<<"Rename as follows:"<< Endl; for(inti =0; I < allset.size (); i++) {Upperchars[i] =' A '+ i;cout<< Upperchars[i] <<":"<< allset.at (i)->SETJ << Endl; } vector<relation*>Newrelvec;//Relvec after renaming for(inti =0; I < relvec.size (); i++) {relation* Newrel =NewRelation ();stringPrenew, Nextnew; ChangeName (Allset, relvec.at (i)->prej, prenew); ChangeName (Allset, relvec.at (i)->NEXTJ, nextnew); newj* Tprej =NewNEWJ (); newj* TNEXTJ =NewNEWJ (); Newrel->prej = Tprej; NEWREL->NEXTJ = TNEXTJ; NEWREL->PREJ->SETJ = prenew; NEWREL->NEXTJ->SETJ = nextnew; Newrel->jchar = relvec.at (i)->jchar; Newrelvec.push_back (Newrel); }//output validation of renamed collection Relationships cout<<"Final conversion:"<< Endl; vector<relation*>:: Iterator Newreliter; for(Newreliter = Newrelvec.begin (); Newreliter! = Newrelvec.end (); newreliter++) {cout<< Endl << (*newreliter)->PREJ->SETJ <<" "<< (*newreliter)->jchar <<" "<< (*newreliter)->nextj->setj << Endl; }//Derive initial state and acceptance status cout<<"Accept status is:"<< Endl;intoutsize = Allset.size ();Char*output =New Char[Outsize];memset(Output,0,sizeof(Char) *outsize);intoutputcnt =0; for(intK =0; K < Allset.size (); k++) { for(inti =0; I < endnode.length (); i++) {if((allset.at (k)->setj). Find (Endnode[i])! =string:: NPOs) output[outputcnt++] =' A '+ K; } }//Array de-heavy output Char*outsfinal =New Char[OUTPUTCNT]; Uniquechars (output, outputcnt, outsfinal); for(inti =0; i < outputcnt; i++) {if(Outsfinal[i]! =' + ')cout<< outsfinal[i]<<" "; } System ("Pause");}
The code has a more detailed comment that can be tested for any form of NFA-to-DFA conversion.
Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.
NFA to DFA Conversion