编译原理的亿点点作业

用某种高级语言写出:

(1)将正规式变成NFA的算法;

(2)将NFA确定化的算法;

(3) DFA状态最少化的算法。

写完就完事了  , 没咋测试拉       

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e2+5;
struct edge{
	char value;
	int to;
};
vector<edge> v[maxn<<2];
int id=0;
string s;
//-------------------------NFA---------------------------//
stack<int> st,ed,str;
void print_nfa(){
	cout<<s<<"的NFA是:"<<endl; 
	for(int i=0;i<=id;++i){
		for(auto it:v[i]){
			cout<<i<<"--"<<it.value<<"->"<<it.to<<endl;
		}
	}
} 
void connection(char ch){
	int nst,nsst;
	nst=st.top();
	st.pop();
	nsst=st.top();
	if(ch!='@') v[nsst].push_back({ch,nst});
} 
void run1(){// '('
	ed.push(++id);//这个括号的结束节点 
	str.push('(');
}
void run2(){// ')'
	int nst=st.top(),nsst;
	int ned=ed.top();
	v[nst].push_back({'^',ned});//'^'代表空串,先将最后一个字符产生的节点连接到结束节点 
	char ch=str.top();
	while(ch!='('){//将括号内的连起来 
		connection(ch);
		str.pop();
		ch=str.top();
	}
	str.pop();
	str.push('@');
	//括号这个整体的占位符,因为处理括号时处理了这个整体与前面的连接,故跳过 
	ned=ed.top(); 
	st.push(ned);//这样就可视括号整体为一个普通字符了 
	ed.pop();
}
void run3(){// '|'
	int nst=st.top();
	int ned=ed.top();
	v[nst].push_back({'^',ned});
	char ch=str.top();
	while(ch!='(' && ch!='S'){//将'|'前的连接 
		connection(ch);
		str.pop();
		ch=str.top();
	}
}
void run4(){// '*'
	//有如a*或()*因为上述处理都视为a 
	int nst=st.top();
	st.pop();
	int nsst=st.top();
	v[nst].push_back({'^',nsst});
	v[nsst].push_back({'^',nst});
	st.push(nst);
}
void run5(char c){// 普通字符 
	str.push(c);
	st.push(++id);//是这个字符的结束,下一个字符的开始标记 
}
void nfa(){
	str.push('S');
	st.push(id);//全串的开始为0,结束为1 
	ed.push(++id);
	for(char c:s){
		if(c=='(') run1(); 
		else if(c==')') run2();
		else if(c=='|') run3();
		else if(c=='*') run4();
		else run5(c);
	}
	char ch=str.top();
	if(st.top()!=0) v[st.top()].push_back({'^',1});
	//后面的开始即前串的结束,将其连接到结束标记1 
	while(ch!='S'){ 
		connection(ch);
		str.pop();
		ch=str.top();
	}
	print_nfa();
} 

//------------------------DFA--------------------------//

int did=0;
vector<edge> dfav[maxn<<2];//dfa下的图 
struct node{
	bool fg;//1表示还有终态,反之无 
	set<int> ns;//集合 
}; 
unordered_map<int,node > mp;//dfa中的序号,序号包含的node集合 
bool vis[maxn<<2];
bool svis[maxn<<2];
set<char> diff;//不同的字符 
node bfs(set<int> u,char c){ //在原图中从u集合出发只能走c的集合 
	memset(vis,0,sizeof(vis));
	queue<int> q;
	for(auto t:u){
		q.push(t);
	}
	set<int> tv;
	bool bfg=0;
	while(!q.empty()){
		int tp=q.front();
		q.pop();
		for(auto it:v[tp]){
			if(it.value!=c) continue;
			else{
				if(vis[it.to]==1) continue;
				else {
					vis[it.to]=1;
					tv.insert(it.to);
                    if(c=='^') q.push(it.to); 
					if(it.to==1) bfg=1;//包含终态 
				}
			}
		}
	}
	return node{bfg,tv};
}

bool check(set<int> x,set<int> y){//比较两个集合的关系 
	//0:相同 1:不同 
	if((int)x.size()!=(int)y.size()) return 1;
	set<int>::iterator ix,iy;
	for(ix=x.begin(),iy=y.begin();ix!=x.end();++ix,++iy){
		if(*ix!=*iy) return 1;
	}
	return 0;
} 

node merge(node a,node b){//合并集合 
	node c;
	if(a.fg || b.fg)	c.fg=1;
	c.ns.insert(a.ns.begin(),a.ns.end());
	c.ns.insert(b.ns.begin(),b.ns.end());
	return c;
}

void print_set(set<int> s){
	cout<<"集合为:";
	for(auto i:s){
		cout<<i<<" ";
	}
	cout<<endl;
}
void print_dfa(){
	cout<<"序号集合:"<<endl;
	for(int i=0;i<=did;++i){
		cout<<i<<" ";
		if(mp[i].fg) cout<<"是终态,";
		else cout<<"不是终态,"; 
		print_set(mp[i].ns);
	} 
	cout<<"DFA是:"<<endl; 
	for(int i=0;i<=did;++i){
		for(auto it:dfav[i]){
			cout<<i<<"--"<<it.value<<"->"<<it.to<<endl;
		}
	}
	
}

void dfa(){
	set<int> nu;
	node nd;
	for(int i=0;i<=id;++i){
		for(auto it:v[i]){
			if(it.value!='^') diff.insert(it.value);
		}
	}
	nu.insert(0);
	nd=bfs(nu,'^');
	mp[0]=nd;
	queue<int> q;
	q.push(0);
	nu.clear(),svis[0]=1;
	while(!q.empty()){
		int tp=q.front();
		q.pop();
		set<int> tpset=mp[tp].ns; 
		for(char c:diff){//先走一个c再走一个空 
			node cnd=bfs(tpset,c);
			node knd=bfs(cnd.ns,'^');
			knd=merge(cnd,knd);
			if(!knd.ns.size()) continue; //空集out 
			bool type=check(tpset,knd.ns);//knd.ns:走出来的集合
			
			//验证是否产生新集合 0:相同,1:不同 
			bool ffg=0; 
			for(auto it:mp){
				if(!check(it.second.ns,knd.ns)){//与以前的集合相同 
					dfav[tp].push_back({c,it.first});
					ffg=1;
					break; 
				}
			} 
			if(ffg) continue;
			//产生了新的集合 
			mp[++did]=knd;
			dfav[tp].push_back({c,did});
			q.push(did); 
		}	
	}
	print_dfa();
}

//------------------------Min_DFA--------------------------//
vector<edge> miv[maxn<<2];
int fa[maxn<<2];
vector<set<int> >setv;
unordered_map<char,int> myhash;//字符映射
int charnum; 
int matrix[maxn<<1][maxn<<1];//变换矩阵 
void init(){
	setv.clear();
	charnum=-1;
	for(char c:diff) myhash[c]=++charnum; //字符映射为数字 构造变换矩阵 
	for(int i=0;i<=did;++i){
		for(int j=0;j<=charnum;++j) matrix[i][j]=-1;
	}
	for(int i=0;i<=did;++i){
		for(auto it:dfav[i]){
			matrix[i][myhash[it.value]]=it.to;
		}
	}
}

int sec(int u){
	return u==fa[u]?u:fa[u]=sec(fa[u]); 
}

void unit(int x,int y){
	x=sec(x),y=sec(y);
	if(x==y) return;
	fa[y]=x;
}

void unitset(set<int> s){//合并集合 
	for(auto i:s) fa[i]=i;
	set<int>::iterator it;
	for(it=s.begin();it!=s.end();++it){
		if(it!=s.begin()){
			int a=*it,b=*(--it);
			++it;
			unit(a,b);
		} 
	}
} 

pair<bool,vector<set<int> > > divide(set<int> ns,char c){//根据c来划分子集 
	//1:不可拆分  0可拆分,则返回一个集合簇
	set<int> allfa;
	vector<set<int> > res;
	bool fg=0;
	for(int i:ns){
		if(matrix[i][myhash[c]]==-1) allfa.insert(-1),fg=1;
		else allfa.insert(sec(i));
	}
	if(allfa.size()==1) return make_pair(1,res);
	if(fg){ //-1,即没有c,单独考虑 
		set<int> newset;
		for(int i:ns){
			if(matrix[i][myhash[c]]==-1) newset.insert(i);
		}
		res.push_back(newset);
	}
	for(auto nfa:allfa){
		if(nfa==-1) continue; 
		set<int> newset;
		for(int i:ns){
			if(sec(matrix[i][myhash[c]])==nfa) newset.insert(i); 
		}
		res.push_back(newset);
	}
	for(auto nset:res) unitset(nset);//分子集之后,重新单独合并 
	return make_pair(0,res);
}

pair<bool,vector<set<int> > > check(set<int> ns){//检验每个集合变化状态是否相同 
	//1:可视为一整体  0需要拆分,则返回一个集合簇 
	vector<set<int> > res,run;
	if(ns.size()==1){//单个元素无法拆分 
		return make_pair(1,res);
	}
	set<int>::iterator it;
	run.push_back(ns);
	bool allflag=1;
	while( (int)run.size()!=0 ){//直到每个子集都不可划分 
		bool fg=0;
		vector<set<int> > tp;
		for(auto nset:run){
			bool nsetflag=1;
			for(char c:diff){
				pair<bool,vector<set<int> > > p= divide(nset,c);
				if(p.first==0){
					allflag=0;
					nsetflag=0;
					tp.insert(tp.end(),p.second.begin(),p.second.end());
					break;
				}
			}
			if(nsetflag){//说明这个子集暂时不可拆分了 
				res.push_back(nset); 
			}
		}
		run=tp;
	} 
	return make_pair(allflag,res);	
}

void min_dfa(){//对dfav进行最小化 
	//vector<int> dfav[] 记录了图 
	//map<int,node> mp 记录了点的信息 
	init();//初始化 
	set<int> end_state,initial_state;
	for(auto it:mp){
		if(it.second.fg){//终态 
			end_state.insert(it.first);
		}
		else initial_state.insert(it.first);//初态 
	}
	unitset(initial_state);
	unitset(end_state);
	setv.push_back(end_state);
	setv.push_back(initial_state);
	while(1){
		bool flag=1; 
		vector<set<int> > tp;
		for(auto nset:setv){
			pair<bool,vector<set<int> > > np=check(nset);
			if(np.first==0) flag=0;
			tp.insert(tp.end(),np.second.begin(),np.second.end());
		}
		setv=tp;
		if(flag) break;//已经全都不可拆分 
	}
	//构图 
	for(auto nset:setv){//每个集合选一个代表 
		char rep=sec(*(nset.begin()));
		for(auto c:diff){
			if(matrix[rep][myhash[c]]==-1) continue;
			miv[rep].push_back({c,sec(matrix[rep][myhash[c]])});
		} 
	} 
}
int main(){
	cout<<"输入正规式:";
	cin>>s;
	nfa(); 
	dfa();
	min_dfa();
	return 0;
}

/* 
输入正规式:a|b*
a|b*的NFA是:
0--a->2
0--^->3
0--b->3
2--^->1
3--^->0
3--^->1
序号集合:
0 是终态,集合为:0 1 3
1 是终态,集合为:1 2
DFA是:
0--a->1
0--b->0
*/ 







 







 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值