学习和掌握将NFA转为DFA的子集构造法。
(1)存储NFA与DFA;
(2)编程实现子集构造法将NFA转换成DFA。
(1)确定NFA与DFA的存储格式。
要求为3个以上测试NFA准备好相应有限自动机的存储文件。(可利用实验一(二)的基础)
(2)用C或JAVA语言编写将NFA转换成DFA的子集构造法的程序。
(3)测试验证程序的正确性。
测试不易。可求出NFA与DFA的语言集合的某个子集(如长度小于某个N),再证实两个语言集合完全相同!
(4)测试用例参考:将下列语言用RE表示,再转换成NFA使用:
(a) 以a开头和结尾的小字字母串;a (a|b|…|z)*a | a
(b) 不包含三个连续的b的,由字母a与b组成的字符串;( | b | bb) (a | ab | abb)*
(c) (aa|b)(a|bb)
学会编程实现等价划分法最小化DFA。
先完善DFA,再最小化DFA。
(1)准备3个以上测试DFA文件。(提示:其中一定要有没有最小化的DFA)
(2)DFA手动完善。(状态转换映射要是满映射)
(3)用C或JAVA语言编写用等价划分法最小化DFA的程序。
(4)经测试无误。测试不易。可求出两个DFA的语言集合的某个子集(如长度小于某个N),再证实两个语言集合完全相同!
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
ifstream input("./in1.dfa.txt");
ofstream output;
struct State_DFA //DFA的状态
{
char name=NULL;
char fat=NULL;
char to=NULL;
set<int>char_set; //状态集合中的元素
};
int s; //NFA开始状态
int id[15]; //状态转换
int num=0; //状态最大值
char DFA_S; //DFA的开始状态
char NFA[15][15]; //NFA的跳转表
char DFA[15][15]; //DFA的跳转表
char DFA_min[15][15]; //最小化DFA
char example[15]; //字符数组
bool emp=0; //判断是否含有空串
set<int>State_NFA; //NFA的状态集
set<char>Char_set; //字符集合
set<string>string_DFA_SET; //DFA所有合法的字符串
set<string>string_NFA_SET; //NFA所有合法的字符串
set<string>string_MIN_SET; //最小化DFA所有的合法字符串
set state; //DFA的状态集合
set<int>e; //接受状态集合
set<char>DFA_E; //DFA的接受状态
set<char>DFA_NE; //DFA的非终止状态
set<char>DFA_MIN_E; //最小化DFA的终止状态
vector<set<char>>v; //最小化DFA集合
bool readfile(){
string temp;
int line=0;
while(getline(input,temp)){
int len=temp.length();
if(line==0){
int x=0;
while(xwhile(temp[x]==' '&&xelse if(line==1){
int x=0;
while(xwhile(temp[x]==' '&&xint sum=0;
while(x' ') sum=sum*10+temp[x]-'0',x++;
State_NFA.insert(sum);
num=num>sum?num:sum;
x++;
}
}
else if(line==2){
s=temp[0]-'0';
}
else if(line==3){
int x=0;
while(xwhile(temp[x]==' '&&xint sum=0;
while(x' ') sum=sum*10+temp[x]-'0',x++;
e.insert(sum);
x++;
}
}
else if(line>3){
int sum=0;
int y=0;
while(temp[y]!=' ') sum=sum*10+temp[y]-'0',y++;
y++;
char c=temp[y];
if(c=='#') emp=1;
int sum1=0;
y+=2;
while(y10+temp[y]-'0',y++;
NFA[sum][sum1]=c;
}
line++;
}
return 1;
}
void flyod(){
for(int x=0;x<=num;x++)
for(int y=0;y<=num;y++)
for(int z=0;z<=num;z++)
if(NFA[x][z]=='#'&&NFA[z][y]=='#') NFA[x][y]='#';
}
bool DfatoNfa(){
int sum=0;
State_DFA *start=new State_DFA;
start->char_set.insert(s);
start->name='A'+sum;
queue q;
DFA_S = start->name;
q.push(start);
while(!q.empty()){
State_DFA *t=q.front(); //取队列中的元素
q.pop();
set<int>::iterator it=(t->char_set).begin();
while(it!=(t->char_set).end()){ //求当前状态的闭包
for(int x=0;x<=num;x++)
if(NFA[*it][x]=='#')
t->char_set.insert(x);
it++;
}
if(t->char_set.size()==0) continue; //状态为空,直接丢弃
//判断集合中是否存在当前状态
int ok=0;
if(state.size()!=0&&t->char_set.size()!=0){
set ::iterator s=state.begin();
for(;s!=state.end();s++){
if((*s)->char_set.size()!=t->char_set.size()) continue;
set<int>::iterator a=t->char_set.begin();
set<int>::iterator b=(*s)->char_set.begin();
while(*a==*b&&a!=t->char_set.end()&&b!=(*s)->char_set.end()) a++,b++;
if(a==(t->char_set.end())&&b==((*s)->char_set.end())){
DFA[(t->fat)-'A'][(t->to)-'a']=(*s)->name;
ok=1;
}
}
}
if(ok) continue; //如果已经存在该集合,continue;
if(t->char_set.size()!=0) { //得到新状态
t->name='A'+sum;
sum++;
state.insert(t); //插入状态集合
set<int>::iterator i = t->char_set.begin();
for(;i!=t->char_set.end();i++){
if(e.count(*i)==1) {
DFA_E.insert(t->name);
break;
}
}
if(i==t->char_set.end()) DFA_NE.insert(t->name);
if(t->fat!=NULL)
DFA[(t->fat)-'A'][(t->to)-'a']=t->name;
}
set<char>::iterator i=Char_set.begin();
for(;i!=Char_set.end();i++){ //扩展新状态
State_DFA *c=new State_DFA;
c->fat=t->name;
c->to=*i;
it=(t->char_set).begin();
for(;it!=(t->char_set).end();it++) {
for(int x=0;x<=num;x++){
if(NFA[*it][x]==*i) (c->char_set).insert(x);
}
}
q.push(c); //加入队列中
}
}
}
void show_DFA(){ //打印DFA状态集合
set ::iterator it=state.begin();
for(;it!=state.end();it++){
cout<<(*it)->name<<" : {";
set<int>::iterator jt=(*it)->char_set.begin();
for(;jt!=(*it)->char_set.end();jt++){
cout<<*jt<<" ";
}
cout<<"}"<void show_table(){ //打印DFA跳转表
int len=Char_set.size();
int len1=state.size();
cout<<" ";
char s='a';
for(int x=0;xcout<<" "<cout<'A';
for(int x=0;xcout<" ",s++;
for(int y=0;ycout<" ";
}
cout<void NFA_show(int N,int x1,int sta){ //打印NFA所有合法的规则字符串
if(x1==N){
int ok=1;
for(int x=s;x<=num;x++)
if(NFA[sta][x]=='#'&&emp==1&&e.count(x)==1) ok=0;
if(ok==1&&e.count(sta)!=1) return ;
string temp;
for(int x=0;xreturn ;
}
for(int y=s;y<=num;y++){
if(Char_set.count(NFA[sta][y])||(emp==1&&NFA[sta][y]=='#')){
if(NFA[sta][y]!='#'){
example[x1]=NFA[sta][y];
NFA_show(N,x1+1,y);
}
else
NFA_show(N,x1,y);
}
}
}
void DFA_show(int N,int x1,char sta){ //打印DFA所有合法的规则字符串
if(x1==N){
if(DFA_E.count(sta)!=1) return ;
string temp;
for(int x=0;xreturn ;
}
set<char>::iterator it=Char_set.begin();
for(;it!=Char_set.end();it++){
// cout<
if(DFA[sta-'A'][*it-'a']!=' '){
example[x1]=*it;
if(*it=='#')
continue;
DFA_show(N,x1+1,DFA[sta-'A'][*it-'a']);
}
}
}
void DFA_MIN_show(int N,int x1,char sta){ //打印最小化DFA的所有合法字符
if(x1==N){
if(DFA_MIN_E.count(sta)!=1) return ;
string temp;
for(int x=0;xreturn ;
}
set<char>::iterator it=Char_set.begin();
for(;it!=Char_set.end();it++){
if(DFA_min[sta-'A'][*it-'a']!=' '){
example[x1]=*it;
if(*it=='#')
continue;
DFA_MIN_show(N,x1+1,DFA_min[sta-'A'][*it-'a']);
}
}
}
void DFA_MIN(){ //最小化DFA
queue<set<char>>q;
q.push(DFA_NE);
q.push(DFA_E);
while(!q.empty()){
set<char>temp=q.front();
set<char>temp1=temp;
int y=0;
q.pop();
if(temp.size()==1){
v.push_back(temp);
continue;
}
set<char>::iterator s=Char_set.begin();
for(;s!=Char_set.end();s++){
set<char>::iterator it=temp.begin();
char cmp;
for(;it!=temp.end();){
char t=DFA[*it-'A'][*s-'a'];
if(it==temp.begin()) cmp=t;
if(t!=' '&&t!=cmp&&temp1.count(t)==0){
set<char>temp2;
temp2.insert(*it);
temp.erase(it++);
q.push(temp2);
y=1;
}
else
it++;
}
}
if(y==1&&temp.size()!=0) q.push(temp);
if(!y){
char t=*(temp.begin());
int len=Char_set.size();
int len1=state.size();
for(int x=0;xfor(int y=0;yif(temp.count(DFA[x][y])!=0) DFA[x][y]=t;
}
}
v.push_back(temp);
}
}
}
void show_DFA_SET(){ //最小化DFA和DFA的状态转换
sort(v.begin(),v.end(),[=](set<char>a,set<char>b){return *(a.begin())<*(b.begin());});
char s='A';
for(int x=0;xcout<":{";
set<char>::iterator s1=v[x].begin();
for(;s1!=v[x].end();s1++){
cout<<*s1<<" ";
if(DFA_E.count(*s1)==1) DFA_MIN_E.insert(s);
id[*s1-'A']=x;
}
s++;
cout<<"}"<void show_MIN_table(){ //最小化DFA的跳转表
set<char>temp;
for(int x=0;xint len=temp.size();
int len1=Char_set.size();
int len2=state.size();
int x=0,x1=0;
while(xif(temp.count('A'+x1)==0){
x1++;continue;
}
for(int y=0;ychar s2='a',s1='A';
cout<<" ";
for(int x=0;xcout<<" "<cout<for(int x=0;xcout<for(int y=0;yif(DFA_min[x][y]!=' ')
DFA_min[x][y]=id[DFA_min[x][y]-'A']+'A';
cout<<" "<cout<int main()
{
memset(NFA,'0',sizeof(NFA));
memset(DFA,' ',sizeof(DFA));
memset(id,0,sizeof(id));
if(!readfile()){
printf("文件打开错误!\n");
return 0;
}
flyod();
DfatoNfa();
int N;
cout<<"得到的DFA集合;"<cout<<"得到的DFA转换表:"<cout<<"得到的DFA最小化集合:"<cout<<"得到的最小化DFA转换表;"<set<char>::iterator d=DFA_MIN_E.begin();
cout<<"输入N的大小:"<cin>>N;
cout<<"NFA的合法字符串为:"<for(int x=1;x<=N;x++){
NFA_show(x,0,s);
}
set<string>::iterator it=string_NFA_SET.begin();
for(;it!=string_NFA_SET.end();it++)
cout<<*it<cout<<"DFA的合法字符串为:"<for(int x=1;x<=N;x++){
DFA_show(x,0,'A');
}
it=string_DFA_SET.begin();
for(;it!=string_DFA_SET.end();it++)
cout<<*it<cout<<"DFA最小化的合法字符串为:"<for(int x=1;x<=N;x++){
DFA_MIN_show(x,0,'A');
}
it=string_MIN_SET.begin();
for(;it!=string_MIN_SET.end();it++)
cout<<*it<
a b
0 1 2 3 4 6 7 8 9 10
0
10
0 # 1
0 # 7
1 # 2
1 # 4
2 a 3
3 # 6
4 b 5
5 # 6
6 # 1
6 # 7
7 a 8
8 b 9
9 b 10
a b
1 2 3 4
1
3
1 a 2
1 b 1
1 # 3
2 a 1
3 a 3
3 b 4
4 b 3
a b
0 1 2 3 4 5 6 7 8 9
0
9
0 # 1
1 a 2
1 # 3
2 b 1
3 # 4
3 # 5
4 a 4
4 # 6
5 b 5
5 # 6
6 # 7
7 b 8
8 a 7
7 # 9