子集法NFA转DFA
来源:互联网 发布:数据有效性设置借贷平 编辑:程序博客网 时间:2024/06/05 17:37
词法分析中重要的一步是NFA的确定化,一般是通过子集法来确定化!并且,有定理:设L是由一NFA接受的正规集,则存在一个DFA接受L。
子集法的算法如下:
设NFA为M=(K,Σ,f,S0,Z),则构造相应的DFA M′=(Q,Σ,f′,I0,F)
1取I0=S0;
2对于状态集Q中任一尚未标记的状态qi={Si1,Si2,…,Sim},Sik∈K,做:
(1) 标记qi;
(2) 对于每个a∈Σ,置
T=f({Si1,Si2,…,Sim},a)
qj=εCLOSURE(T)
(3) 若qj不在Q中,则将qj作为一个未加标记的状态添加到Q中,且把状态转移f′(qi,a)=qj添加到M′。
3重复进行步骤2,直到Q中不再含有未标记的状态为止。对于由此构造的Q,我们把那些至少含有一个Z中的元素的qi作为M′的终态。
#include<map>using namespace std;class StateTransitionDiagram{public:StateTransitionDiagram();//constructorStateTransitionDiagram(int s);//constructor with a initial valueint getNode();//get the value of the nodemultimap<char, int> getTransitionMatrix();//get the transition matrixvoid addTransition(char val,int n);//add transition to the current nodevoid print();//print the graphprivate:int node; //the number of the nodemultimap<char, int>transitionMatrix;//record the state transition};
节点类函数实现:
#include"StateTransitionDiagram.h"#include<map>#include<iostream>using namespace std;StateTransitionDiagram::StateTransitionDiagram(){node = 0;}StateTransitionDiagram::StateTransitionDiagram(int n){node = n;}int StateTransitionDiagram::getNode(){return node;}multimap<char, int> StateTransitionDiagram::getTransitionMatrix(){return transitionMatrix;}void StateTransitionDiagram::addTransition(char v,int n){transitionMatrix.insert(make_pair(v,n));}void StateTransitionDiagram::print(){for (multimap<char, int>::iterator it = transitionMatrix.begin(); it != transitionMatrix.end(); ++it)cout << "node:" << node << " edge value:" << it->first << " node:" << it->second << endl;}
NFA转DFA主要代码:
#include"StateTransitionDiagram.h"#include<iostream>#include<deque>#include<map>#include<set>#include<stack>#include<vector>using namespace std;#define EPSILON '#'typedef deque<StateTransitionDiagram*>NFA; //define NFA with a deque,and the type of the element in the deque id StateTransitionDiagramtypedef deque<StateTransitionDiagram*>DFA;//same with NFAtypedef set<int>::iterator set_it;typedef multimap<char, int>::iterator multimap_it;void NFAtoDFA(); //determine the NFA with subset methodset<int> epsilonClosure(set<int> &s); //epsilon closuremultimap<char, int> getTranMatrix(int n); //get the transition matrix of the node nset<int>getSet(set<int>&,char); //get set when input a charbool getUnhandled(multimap<set<int>, int>::iterator &it); //judge whether the node is handledmap<set<int>, int>dfaTran; //transition in the dfaset<char> inputChar; //input charvector<int>dfaT;vector<int>nfaT;NFA nfa; //nfaDFA dfa; //dfaint main(){StateTransitionDiagram *n0 = new StateTransitionDiagram();StateTransitionDiagram *n1 = new StateTransitionDiagram(1);n0->addTransition('a',0);n0->addTransition('b',1);n1->addTransition('a',1);n1->addTransition('a', 0);n1->addTransition('b', 0);inputChar.insert('a');inputChar.insert('b');nfa.push_back(n0);nfa.push_back(n1);nfaT.push_back(1);NFAtoDFA();cout << "---------------------------NFA----------------------------" << endl;for (NFA::iterator it = nfa.begin(); it != nfa.end(); ++it)(*it)->print();cout << "Terminal statein NFA:";for (vector<int>::iterator it=nfaT.begin(); it != nfaT.end(); ++it)cout << *it << " ";cout << endl;cout << "---------------------------DFA----------------------------" << endl;for (DFA::iterator it = dfa.begin(); it != dfa.end(); ++it)(*it)->print();cout << "Terminal statein NFA:";for (vector<int>::iterator it = dfaT.begin(); it != dfaT.end(); ++it)cout << *it << " ";cout << endl;return 0;}multimap<char, int> getTranMatrix(int n){multimap<char, int>multim;NFA::iterator it;//find the postion of the node nfor (it = nfa.begin(); it != nfa.end(); ++it){if (n == (*it)->getNode()){multim = (*it)->getTransitionMatrix();break;}}return multim;}set<int>epsilonClosure(set<int> &s){set<int> closureSet = s; //first, add the initial set to the closure setstack<int>nodeStack; //save all the nodeint currentNode; //the node being handlingfor (set_it it = closureSet.begin(); it != closureSet.end(); ++it)nodeStack.push(*it);while (!nodeStack.empty()){//get the node in the top of the state stackcurrentNode = nodeStack.top();nodeStack.pop();//get the transition matrixmultimap<char, int> tranMax = getTranMatrix(currentNode);for (multimap_it it = tranMax.begin(); it != tranMax.end(); ++it){//if the edge is epsilon and the node is not included in the set,then add the node if (it->first == EPSILON && closureSet.find(it->second)==closureSet.end()){closureSet.insert(it->second);nodeStack.push(it->second);}}}return closureSet;}set<int>getSet(set<int> &s, char ch){set<int>ss;stack<int>nodeStack;multimap<char, int>mmap;for (set_it it = s.begin(); it != s.end(); ++it)nodeStack.push(*it);while (!nodeStack.empty()){//get the transition matrixmmap = getTranMatrix(nodeStack.top());nodeStack.pop();for (multimap_it it = mmap.begin(); it != mmap.end(); ++it){//if match the ch,then add it into the setif (it->first == ch){ss.insert(it->second);}}}return ss;}bool getUnhandled(multimap<set<int>, int>::iterator &it){for ( it= dfaTran.begin(); it != dfaTran.end(); ++it){if (it->second < 0)return true;}return false;}void NFAtoDFA(){//initiate dfa with the initial state of nfaset<int> s;s.insert(0);dfaTran.insert(make_pair(s,0));map<set<int>, int>::iterator map_it = dfaTran.begin();//constructor the DFAdo{s = map_it->first;map_it->second = abs(map_it->second);//create a new node, if map_it is negtive,the state is not handled,otherwise,handledStateTransitionDiagram *sTranNode = new StateTransitionDiagram(map_it->second);dfa.push_back(sTranNode);//find the terminal nodefor (vector<int>::iterator it = nfaT.begin(); it != nfaT.end(); ++it){if (s.find(*it) != s.end()){dfaT.push_back(map_it->second);}}for (set<char>::iterator it = inputChar.begin(); it != inputChar.end(); ++it){set<int>tempSet = epsilonClosure(getSet(s,*it));if (!tempSet.empty())//if the set is empty,then no edge{if (dfaTran.find(tempSet) == dfaTran.end()){dfaTran.insert(make_pair(tempSet,-(int)dfaTran.size()));}map_it = dfaTran.find(tempSet);sTranNode->addTransition(*it,abs(map_it->second));}}} while (getUnhandled(map_it));}
代码的实现用到了很多STL里面的类库,STL确实很强大,节省了很多的开发时间,灵活使用STL需要更多的实践经验。编译原理解释了程序的执行原理,如果能理解透彻其中的深层次原理,对编程本身也是一种很大的提升,如果能自己去构造一个编译器,亲身去实现其中的算法,可以想象。不过这确实需要很大的耐心,对编程能力也有很高的要求!少年,任重而道远,加油吧!
0 0
- 子集法NFA转DFA
- 【编译原理】:NFA转变为DFA的子集构造法
- 【编译原理】:NFA转变为DFA的子集构造法
- NFA(子集算法,DFA最小化)代码实现
- [转]NFA/DFA算法
- Java , NFA转DFA
- NFA转DFA与DFA化简
- (zz)NFA转DFA
- NFA转DFA 《编译原理》
- DFA&NFA
- nfa&dfa
- NFA/DFA
- NFA/DFA算法
- NFA转化DFA
- DFA和NFA
- DFA和NFA
- DFA和NFA
- 正则表达式 DFA NFA
- 两个Python web框架:Django & Tornado比较
- 学会转弯也是人生的智慧
- 代理服务器Squid3的配置
- GCC Makefile说明
- 黑马程序员-OC-构造方法
- 子集法NFA转DFA
- Scala从零开始:使用Intellij IDEA写hello world
- 深刻理解Java中的String、StringBuffer和StringBuilder的区别
- 网站优化如何选网站关键词
- linux下mysql密码重置方法以及问题处理
- eclipse中web项目部署以后jsp的java文件找不到问题(Tomcat配置serverlocations)
- 【DP_背包专辑】【10.14最新更新】
- jQuery实现类似腾讯图片频道的图片播放器
- 【转】VIM学习