编译原理林瀚期末大作业-Source code

#include <iostream>
#include <cstring>
#include <vector>
#include <stack>
#include <map>
#include <string>
#include <algorithm>
using namespace std;
const int maxn = 200;  // 状态数的最多数 
const int maxm = 27;    // a-z和E共27个字母 
unsigned N, M;		//N表示状态数,M表示输入正则表达式含有的字母数 
string s;			//s是输入的正则表达式 
string alphabet( "abcdefghijklmnopqrstuvwxyzE)*+?" );//正则表达式中需要构造子NFA的字符
stack<char> char_operator;   //存储操作符 
stack< pair<int, int> > nfa; 
vector<int> NFA[ maxn ][ maxm ];//NFA的状态转移表

/*******正则表达式转NFA*********/
/*遇到闭包运算符*/
void star_NFA() {
	pair<int, int> new_nfa;   //新建一个NFA       
	new_nfa.first = N++;		//这行和下面一行表明总状态数加2 
	new_nfa.second = N++;
	pair<int, int> s = nfa.top();//从栈中弹出一个NFA
	nfa.pop();
	NFA[ new_nfa.first ][ 26 ].push_back( s.first );  /*new_nfa的头通过ε指向s的头*/ 
	NFA[ new_nfa.first ][ 26 ].push_back( new_nfa.second ); /*new_nfa的头通过ε指向new_nfa的尾*/ 
	NFA[ s.second ][ 26 ].push_back( s.first ); /*s的尾通过ε指向s的头*/ 
	NFA[ s.second ][ 26 ].push_back( new_nfa.second );/*s的尾通过ε指向new_nfa的尾*/ 
	nfa.push( new_nfa );                               /*最后将新生成的NFA入栈*/
}
/*遇到或运算符*/
void or_NFA() {
	char_operator.pop();
	pair<int, int> new_nfa;				 //新建一个NFA
	new_nfa.first = N++;                   //这行和下面一行表明总状态数加2 
	new_nfa.second = N++;
	pair<int, int> s = nfa.top();  	//从栈中弹出两个NFA
	nfa.pop();
	pair<int, int> t = nfa.top();
	nfa.pop();
	NFA[ new_nfa.first ][ 26 ].push_back( s.first );    /*new_nfa的头通过ε指向s的头*/ 
	NFA[ new_nfa.first ][ 26 ].push_back( t.first );	 /*new_nfa的头通过ε指向t的头*/
	NFA[ s.second ][ 26 ].push_back( new_nfa.second ); /*s的尾通过ε指向new_nfa的尾*/
	NFA[ t.second ][ 26 ].push_back( new_nfa.second ); /*t的尾通过ε指向new_nfa的尾*/
	nfa.push( new_nfa );								/*最后将新生成的NFA入栈*/
}

/*遇到&运算符*/
void connect_NFA() {
	char_operator.pop();  
	pair<int, int> t = nfa.top();   //从栈中弹出两个NFA
	nfa.pop();
	pair<int, int> s = nfa.top();
	nfa.pop();
	pair<int, int> r( s.first, t.second ); //新建的NFA的头为s的头,尾为t的尾 
	NFA[ s.second ][ 26 ].push_back( t.first );  /*s的尾通过ε指向t的头*/
	nfa.push( r );
}
/*遇到操作数*/ 
void alp_NFA( int i ) {      //0-25表示a-z,26表示E 
	pair<int, int> new_nfa;	//新建一个NFA 
	new_nfa.first = N++;      //NFA状态总数加1
	new_nfa.second = N++;		//NFA状态总数加1 
	NFA[ new_nfa.first ][ i ].push_back( new_nfa.second );//NFA的头指向尾,弧上的值为i对应的字母 
	nfa.push( new_nfa );
}
/*遇到?运算符*/
void question_NFA() {
	pair<int, int> new_nfa;  //新建一个NFA
	new_nfa.first = N++;     //这行和下面一行表明总状态数加2 
	new_nfa.second = N++;
	pair<int, int> s = nfa.top(); //从栈中弹出NFA
	nfa.pop();
	NFA[ new_nfa.first ][ 26 ].push_back( s.first );          /*new_nfa的头通过ε指向s的头*/
	NFA[ new_nfa.first ][ 26 ].push_back( new_nfa.second );  /*t的头通过ε指向new_nfa的尾*/
	NFA[ s.second ][ 26 ].push_back( new_nfa.second );      /*s的尾通过ε指向new_nfa的尾*/
	nfa.push( new_nfa );
}
/*遇到+运算符*/ 
void plus_NFA() {
	pair<int, int> new_nfa;
	new_nfa.first = N++;
	new_nfa.second = N++;
	pair<int, int> s = nfa.top();
	nfa.pop();
	NFA[ new_nfa.first ][ 26 ].push_back( s.first );     /*new_nfa的头通过ε指向s的头*/
	NFA[ s.second ][ 26 ].push_back( s.first );			/*s的尾通过ε指向s的头*/
	NFA[ s.second ][ 26 ].push_back( new_nfa.second );	/*s的尾通过ε指向new_nfa的尾*/
	nfa.push( new_nfa );
}

void REtoNFA() {
	//先将上个表达式的数据清除 
	N = 0;
	for ( int i = 0; i < maxn; i++ ) {
		for ( int j = 0; j < maxm; j++ )
			NFA[ i ][ j ].clear();
	}
	while ( !char_operator.empty() )
		char_operator.pop();
	while ( !nfa.empty() )
		nfa.pop();
	//遍历正则表达式并对相应字符做出处理 
	for ( unsigned i = 0; i < s.size(); i++ ) {		
		if ((s[i] >= 'a' && s[i] <= 'z')||s[i]=='E') {  
			if ( i != 0 && alphabet.find( s[ i - 1 ] ) != string::npos ) { 
				if ( !char_operator.empty() && char_operator.top() == '&' )
					connect_NFA();
				char_operator.push( '&' );
			}
			if(s[i] >= 'a' && s[i] <= 'z')
			alp_NFA( s[ i ] - 'a' ); //操作数在a-z之间 
			else
			{ 
				alp_NFA(26);//空串E对应的数字为26 
			}
		}
		else if ( s[ i ] == '|' ) {		
			while ( !char_operator.empty() && char_operator.top() != '(' ) {
				if ( char_operator.top() == '|' )
					or_NFA();
				else if ( char_operator.top() == '&' )
					connect_NFA();
			}
			char_operator.push( '|' );
		}
		else if ( s[ i ] == '?' )
			question_NFA();
		else if ( s[ i ] == '*' )
			star_NFA();
		else if ( s[ i ] == '+' )
			plus_NFA();
		else if ( s[ i ] == '(' ) {
			if ( i != 0 && alphabet.find( s[ i - 1 ] ) != string::npos ) {
				if ( !char_operator.empty() && char_operator.top() == '&' )
					connect_NFA();
				char_operator.push( '&' );
			}
			char_operator.push( '(' );
		}
		else if ( s[ i ] == ')' ) {
			while ( char_operator.top() != '(' ) {
				if ( char_operator.top() == '|' )
					or_NFA();
				else if ( char_operator.top() == '&' )
					connect_NFA();
			}
			char_operator.pop();
		}
	}

	while ( !char_operator.empty() ) {
		if ( char_operator.top() == '|' )
			or_NFA();
		else if ( char_operator.top() == '&' )
			connect_NFA();
	}
}

/*********NFA转DFA*********/
map< vector<int>, int > trans;//转换表 
//求一个状态集的ε-cloure(T)
vector<int> e_Closure( vector<int> T ) {
	stack<int> temp;
	vector<int>::iterator it;
	int t;
	for ( it = T.begin(); it != T.end(); it++ ) //将T的所有状态压入栈中 
		temp.push( *it );
	while ( !temp.empty() ) {   //当栈非空时
		t = temp.top();       //将栈顶元素t弹出栈中 
		temp.pop();		
		for ( it = NFA[ t ][ 26 ].begin(); it != NFA[ t ][ 26 ].end(); it++ ) {//对每个满足如下条件的it:从 t出发有一个标号为E的转换到达状态it 
			if ( find( T.begin(), T.end(), *it ) == T.end() ) {//如果it不在ε-cloure(T)中 
				T.push_back( *it );//将it加入ε-cloure(T)中 
				temp.push( *it ); //将it压入栈中 
			}
		}
	}
	sort( T.begin(), T.end() );
	return T;
}
//计算move(T,a)
vector<int> move( vector<int> T, int a ) {
    vector<int>::iterator it1, it2;
    vector<int> Set;
    for ( it1 = T.begin(); it1 != T.end(); it1++ ) {
        for ( it2 = NFA[ *it1 ][ a ].begin(); it2 != NFA[ *it1 ][ a ].end(); it2++ ) {
            if ( find( Set.begin(), Set.end(), *it2 ) == Set.end() )
                Set.push_back( *it2 );
        }
    }
	return Set;
}
//子集构造法将NFA转为DFA 
void NFAtoDFA(int dfa[maxn][maxm],bool isFinal[maxn]) {
	//初始数据 
	M = 0;
	trans.clear();
	pair<int, int> r = nfa.top();

	vector<int> T, Set;
	T.push_back( r.first );
	Set = e_Closure( T );
	vector< vector<int> > Dstates;
	stack< vector<int> > s;
	Dstates.push_back( Set );
	s.push( Set );
	trans[ Set ] = M++;
	if ( find( Set.begin(), Set.end(), r.second ) != Set.end() )
	{
		isFinal[M-1]=true;	
	}

	while ( !s.empty() ) {
		T = s.top();
		s.pop();
		for ( int a = 0; a < maxm; a++ ) {
			Set = e_Closure( move( T, a ) );
			if ( find( Dstates.begin(), Dstates.end(), Set ) == Dstates.end() ) {
				Dstates.push_back( Set );
				s.push( Set );
				trans[ Set ] = M++;
				if ( find( Set.begin(), Set.end(), r.second ) != Set.end() )
				{
					isFinal[M-1]=true;					
				}

			}
			dfa[ trans[ T ] ][ a ] = trans[ Set ];
		}
	}
}
 
bool visit[maxn][maxn];
//将状态取反 ,用于求一个dfa的补集 
void back(bool isFinal[maxn],bool noFinal[maxn]) 
{
	for(int i=0;i<maxn;i++)
	{
		if(isFinal[i])
			noFinal[i]=false;
		else
			noFinal[i]=true;
	}
}
//判断当两个DFA此时的状态都为接受态时,返回true
bool receive(int start1,int start2,bool isFinal1[maxn],bool isFinal2[maxn])  
{
	return isFinal1[start1]&&isFinal2[start2];
}
//判断两个dfa是否相交
bool judge(int dfa1[maxn][maxm], int dfa2[maxn][maxm],int start1,int start2,bool isFinal1[maxn],bool isFinal2[maxn],bool visit[maxn][maxn])
{
	visit[start1][start2]=true;
	if (receive(start1,start2,isFinal1,isFinal2)) 
		return true;
	for(int i=0;i<26;i++)
	{
		int next1=dfa1[start1][i];
		int next2=dfa2[start2][i];
		if(!visit[next1][next2])
		{
			if(judge(dfa1,dfa2,next1,next2,isFinal1,isFinal2,visit))
				return true;
			visit[next1][next2]=false;
		}
	}
	return false;
		
}

int main(){
	int dfa1[maxn][maxm],dfa2[maxn][maxm];
	bool isFinal1[maxn],isFinal2[maxn];//是否为终态,终态为true; 
	bool noFinal1[maxn],noFinal2[maxn];//状态的的补集 

	int counts;
	cin>>counts;
	while(counts>0) 
	{
		//初始化
		for(int i=0;i<maxn;i++) 
		{
			for(int j=0;j<maxm;j++)
			{
				dfa1[i][j]=0;
				dfa2[i][j]=0;
			}
			isFinal1[i]=false;
			noFinal1[i]=true;
			isFinal2[i]=false;
			noFinal2[i]=true;
			
		}
		int start1=0,start2=0;   //两个dfa开始状态
		cin>>s;//输入第一个表达式 
		REtoNFA();
		NFAtoDFA(dfa1,isFinal1);
		cin>>s;//输入第二个表达式 
		REtoNFA();
		NFAtoDFA(dfa2,isFinal2);				
		back(isFinal1,noFinal1);//对DFA的状态取补集 
		back(isFinal2,noFinal2);
		memset(visit, false, sizeof(visit));
		bool yes1=judge(dfa1,dfa2,start1,start2,noFinal1,isFinal2,visit);
		memset(visit, false, sizeof(visit)); 
		bool yes2=judge(dfa1,dfa2,start1,start2,isFinal1,noFinal2,visit);
		//判断这两个表达式的关系
		if(yes1&&yes2)   //如果dfa1的补和dfa2相交且dfa1和dfa2的补相交,则两个dfa不是等价关系也不是子集关系
			printf("!\n");
		else if(yes1)   //如果dfa1的补和dfa2相交且dfa1和dfa2的补不相交,则dfa1是dfa2的子集
			printf("<\n");
		else if(yes2)
			printf(">\n"); //如果dfa1的补和dfa2不相交且dfa1和dfa2的补相交,则dfa2是dfa1的子集
		else
			printf("=\n");	//如果dfa1的补和dfa2不相交且dfa1和dfa2的补不相交,则两个dfa是等价关系
		counts--;			
	}
		
	return 0;	
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值