实验三 NFA确定化和DFA最小化

(一)NFA–>DFA(2小时)

一、实验目的

学习和掌握将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最小化(2小时)

一、实验目的

学会编程实现等价划分法最小化DFA。

二、实验任务

先完善DFA,再最小化DFA。

三、实验内容

(1)准备3个以上测试DFA文件。(提示:其中一定要有没有最小化的DFA)
(2)DFA手动完善。(状态转换映射要是满映射)
(3)用C或JAVA语言编写用等价划分法最小化DFA的程序。
(4)经测试无误。测试不易。可求出两个DFA的语言集合的某个子集(如长度小于某个N),再证实两个语言集合完全相同!

源代码:

#include<iostream>
#include<fstream>
#include<stdio.h>
#include<cstring>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<algorithm>
#include<string>
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*>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(x<len){
                while(temp[x]==' '&&x<len) x++;
                Char_set.insert(temp[x]);
                x++;
            }
        }
        else if(line==1){
            int x=0;
            while(x<len){
                while(temp[x]==' '&&x<len) x++;
                int sum=0;
                while(x<len&&temp[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(x<len){
                while(temp[x]==' '&&x<len) x++;
                int sum=0;
                while(x<len&&temp[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(y<len) sum1=sum1*10+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<State_DFA*>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<State_DFA*>::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<State_DFA*>::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<<"}"<<endl;
     }
}
void show_table(){      //打印DFA跳转表
     int len=Char_set.size();
     int len1=state.size();
     cout<<" ";
     char s='a';
     for(int x=0;x<len;x++) cout<<" "<<s,s++;
     cout<<endl;
     s='A';
     for(int x=0;x<len1;x++){
           cout<<s<<" ",s++;
           for(int y=0;y<len;y++){
             cout<<DFA[x][y]<<" ";
           }
           cout<<endl;
     }
}

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;x<N;x++)
        temp+=example[x];
        string_NFA_SET.insert(temp);
        return ;
     }
     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;x<N;x++)
        temp+=example[x];
        string_DFA_SET.insert(temp);
        return ;
     }
     set<char>::iterator it=Char_set.begin();
     for(;it!=Char_set.end();it++){
          //  cout<<NFA[sta][y]<<endl;
         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;x<N;x++)
        temp+=example[x];
        string_MIN_SET.insert(temp);
        return ;
     }
     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;x<len1;x++){
                for(int y=0;y<len;y++){
                    if(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;x<v.size();x++){
         cout<<s<<":{";
         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<<"}"<<endl;
     }
}

void show_MIN_table(){     //最小化DFA的跳转表
     set<char>temp;
     for(int x=0;x<v.size();x++){
        temp.insert(*(v[x].begin()));
     }
     int len=temp.size();
     int len1=Char_set.size();
     int len2=state.size();
     int x=0,x1=0;
     while(x<len&&x1<len2){
            if(temp.count('A'+x1)==0){
                x1++;continue;
            }
            for(int y=0;y<len1;y++){
                DFA_min[x][y]=DFA[x1][y];
        }
        x++;
        x1++;
     }
     char s2='a',s1='A';
     cout<<" ";
     for(int x=0;x<len1;x++) cout<<" "<<s2,s2++;
     cout<<endl;
     for(int x=0;x<len;x++){
            cout<<s1,s1++;
        for(int y=0;y<len1;y++){
            if(DFA_min[x][y]!=' ')
            DFA_min[x][y]=id[DFA_min[x][y]-'A']+'A';
            cout<<" "<<DFA_min[x][y];
        }
        cout<<endl;
     }
}
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集合;"<<endl;
    show_DFA();

    cout<<"得到的DFA转换表:"<<endl;
    show_table();
    DFA_MIN();
    cout<<"得到的DFA最小化集合:"<<endl;
    show_DFA_SET();
    cout<<"得到的最小化DFA转换表;"<<endl;
    show_MIN_table();
    set<char>::iterator d=DFA_MIN_E.begin();
    cout<<"输入N的大小:"<<endl;
    cin>>N;
    cout<<"NFA的合法字符串为:"<<endl;
    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<<endl;
    cout<<"DFA的合法字符串为:"<<endl;
    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<<endl;
    cout<<"DFA最小化的合法字符串为:"<<endl;
    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<<endl;
}

测试一:

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

测试结果:
这里写图片描述
这里写图片描述

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

计算机的小粽子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值