实验二:利用子集构造法实现NFA到DFA的转换
【问题描述】利用子集构造法实现NFA到DFA的转换。NFA的确定化
【输入形式】NFA
参见样例。其中,第一列表示状态名,终状态用f表示;第二列和第三列分别表示输入字符a和b所到达的状态。
【输出形式】DFA
参见样例。其中,第一列表示输入状态名;第二列表示重新命名的状态名,第三列和第四列分别表示输入字符a和b所到达的状态。
【要求】
确定各个子程序的功能并画出流程图
设计子集构造算法
编码、调试通过(C/C++语言编写)
设计3-5个NFA测试实例,检验程序能否输出正确的DFA。
样例中的NFA状态转换矩阵是由下图NFA状态转换图得到
【样例输入】
0 {1} {0,1}
1 {2} {NULL}
2 {2,f} {f}
f {NULL} {NULL}
【样例输出】
{0}ABC
{1}BD
{0,1,}CEC
{2}DFG
{1,2,}EFG
{2,f,}FFG
{f}G
【样例说明】
【评分标准】与输出不一致,0分。完成正确,2分。检查通过,3分。
#include <iostream>
#include <map>
#include <string>
#include <queue>
#include <cctype>
using namespace std;
string END;
const int MAXN=100;
int Max=0;
struct Node
{
string data;
struct Node *next_a,*next_b;
Node(){next_a=next_b=NULL;}
}G[MAXN];
//建图
void Create()
{
string str;
int Max=0;
while(getline(cin,str))
{
if(str.length()<1)break;
int d=int(str[0]-'0');
if(str[0]=='f')d=Max+1;
int a=0,b=0;
string str_a,str_b;
str_a.clear();str_b.clear();
for(int i=1;i<str.length();i++)
{
if(str[i]=='{'&&a==0)
a=i+1;
else if(str[i]=='{'&&a!=0)
{
b=i+1;
break;
}
}
int k=a;
while(str[k]!='}'&&str[k]!='N')
{
if(!(isdigit(str[k])||str[k]=='f'))
{
++k;
continue;
}
str_a+=str[k];
++k;
}
k=b;
while(str[k]!='}'&&str[k]!='N')
{
if(!(isdigit(str[k])||str[k]=='f'))
{
++k;
continue;
}
str_b+=str[k];
++k;
}
Node* p=&G[d];
for(int i=0;i<str_a.length();i++)
{
if(isdigit(str_a[i])&&int(str_a[i]-'0')>Max)
Max=int(str_a[i]-'0');
while(p->next_a!=NULL)
p=p->next_a;
p->next_a=new Node;
p=p->next_a;
p->data=str_a[i];
}
p=&G[d];
for(int i=0;i<str_b.length();i++)
{
if(isdigit(str_b[i])&&int(str_b[i]-'0')>Max)
Max=int(str_b[i]-'0');
while(p->next_b!=NULL)
p=p->next_b;
p->next_b=new Node;
p=p->next_b;
p->data=str_b[i];
}
}
Max++;
for(int i=0;i<=Max;i++) //替换掉所有的f
{
Node* p=G[i].next_a;
while(p!=NULL)
{
if(p->data=="f")
p->data='0'+Max;
p=p->next_a;
}
p=G[i].next_b;
while(p!=NULL)
{
if(p->data=="f")
p->data='0'+Max;
p=p->next_b;
}
}
END+='0'+Max;
}
//输出首元素
void output(string str)
{
cout<<"{";
if(str.length()==1)
{
char c='0'+str[0]-'0';
if(str[0]!=END[0])
cout<<c<<"}";
else cout<<"f"<<"}";
}
else
{
for(int i=0;i<str.length();i++)
{
if(str[i]!=END[0])
cout<<str[i]<<",";
else cout<<"f,";
}
cout<<"}";
}
}
//获取后继状态,k==0是找输入a的,否则是b的
string get_next(Node* p,int k=0)
{
string str;
str.clear();
Node* t=p;
while(t!=NULL)
{
str+=t->data;
if(!k)t=t->next_a;
else t=t->next_b;
}
return str;
}
//删除重复元素
void Del(string &str)
{
string::iterator it=str.begin();
for(;it!=str.end();it++)
{
for(string::iterator it1=it+1;it1<=str.end()-1;it1++)
{
if(*it1==*it)
str.erase(it1);
}
}
}
//输出最终状态
void print()
{
queue<string>Q;
map<string,int>M,M1; //M是输出不重复,M1是用于添加总的
M1["0"]=0;
Q.push("0");
int cur=0;
while(!Q.empty())//&&Q.front()!=END)
{
string tmp=Q.front();
Q.pop();
map<string,int>::iterator it=M.find(tmp);
if(it!=M.end())continue; //不输出重复的
M.insert(pair<string,int>(tmp,M.size()+1));
output(tmp); //输出出发结点
char c='A'+M.size()-1;
cout<<c;
string str_a,str_b; //a存储输入a后的结论,b同理
str_a.clear();str_b.clear();
for(int i=0;i<tmp.length();i++)
{
int d=int(tmp[i]-'0');
str_a+=get_next(G[d].next_a,0);
str_b+=get_next(G[d].next_b,1);
Del(str_a); //删除重复元素
Del(str_b);
}
c='\0'; //初始化清空一次
it=M1.find(str_a);
if(str_a.length()>0&&it==M1.end()) //如果没在集合内部
{
cur++;
c='A'+cur;
M1.insert(pair<string,int>(str_a,cur));
}
else if(str_a.length()>0)
c='A'+M1.find(str_a)->second;
cout<<c; //输出 输入a后的结果
if(str_a.length()>0)
Q.push(str_a);
c='\0'; //初始化清空一次
it=M1.find(str_b);
if(str_b.length()>0&&it==M1.end())
{
cur++;
M1.insert(pair<string,int>(str_b,cur));
c='A'+cur;
}
else if(str_b.length()>0)
c='A'+M1.find(str_b)->second;
if(str_b.length()>0)
Q.push(str_b);
cout<<c<<endl; //输出 输入b后的结果
}
}
int main()
{
Create();
print();
}
/*
0 {0,1} {0,2}
1 {f} {NULL}
2 {NULL} {f}
f {f} {f}
*/