一、实验目的
1.熟练掌握DFA与NFA的定义与有关概念。
2.理解并掌握确定的有穷自动机的最小化等算法。
二、实验要求
输入:DFA
输出:最小化的DFA
三、实验过程
1.化简DFA关键在于把它的状态集分成一些两两互不相交的子集,使得任何两个不相交的子集间的状态都是可区分的,而同一个子集中的任何两个状态都是等价的,这样可以以一个状态作为代表而删去其他等价的状态,然后将无关状态删去,也就获得了状态数最小的DFA。
2.DFA的化简算法:
(1)首先将DFAM的状态划分出终止状态集K1和非终止状态集K2。K=K1∪K2,
由上述定义知,K1和K2是不等价的。
(2)对各状态集每次按下面的方法进一步划分,直到不再产生新的划分。设第i次划分已将状态集划分为k组,即:
(3)重复第〔2〕步,直到每一个集合不能再划分为止,此时每个状态集合
中的状态均是等价的。
(4)合并等价状态,即在等价状态集中取任意一个状态作为代表,删去其他—切等价状态。
(5)假如有无关状态,如此将其删去。根据以上方法就将确定有限自动机进展了简化,而且简化后的自动机是原自动机的状态最少的自动机。
四、实验结果
五、代码实现
#include<iostream>
#include<string>
using namespace std;
#define max 100
struct edge{
string first;//边的初始结点
string change;//边的条件
string last;//边的终点
};
int N;//NFA 的边数
string part[max];//分割子集
//状态集合 I 的 a 弧转换
string move(string jihe,char ch,edge *b)
{
int i,j;
string s="";
for(i=0;i<jihe.length();i++)
{
for(j=0;j<N;j++)
{
if(b[j].first[0]==jihe[i]&&b[j].change[0]==ch)
s=s+b[j].last;
}
}
if(s=="")return "&";
else return s;
}
//判断子串是否存在在某一集合
bool isexist(string s,string d) {
if(d!=""&&0<=d.find(s)&&d.find(s)<=d.length()-1)return 1;
else return 0;
}
//分割子集法进行 DFA 的最小化
int divide(edge *b,string change) {
int x,m,flag=2,flag0,i,j;
string ss,part0[max];
flag0=flag;
for(x=0;x<change.length();x++) {
for(m=0;m<flag0;m++)
{
for(i=0;i<part[m].length();i++) {
ss=move(part[m].substr(i,1),change[x],b);
for(j=0;j<flag;j++) {
if(isexist(ss,part[j]))part0[j]=part0[j]+part[m].substr(i,1); if(ss=="&") {
part0[flag]=part0[flag]+part[m].substr(i,1);
break;
}
}
}
for(j=0;j<=flag;j++) {
if(part0[j]!=""&&part0[j]!=part[m]) {
part[flag++]=part0[j];
part0[j]="";
part[m]="";
}
else part0[j]="";
}
}
flag0=flag;
}
return flag;
}
int main()
{
int i,j,flag,x;
string Change;//输入符号
string ss;
edge *b=new edge[max];
cout<<"-------请输入DFA各边信息:(空用&表示)--------"<<endl<<endl
<<"-----------------以输入$结束----------------"<<endl;
for(i=0;i<max;i++)
{
cin>>b[i].first;
if(b[i].first=="$")break;
else
cin>>b[i].change>>b[i].last;
}
N=i;
cout<<"请输入该DFA的终态集合: "<<endl;
cin>>part[1];
cout<<"请输入该DFA的非终态集合: "<<endl;
cin>>part[0];
cout<<"请输入此DFA状态中的输入符号即边上的条件:"<<endl;
cin>>Change;
flag=divide(b,Change);
cout<<"此DFA最小化划分的子集如下: "<<endl;
for(i=0;i<flag;i++)
{
if(part[i]!="")cout<<part[i]<<endl;
}
cout<<"用状态A,B,C…等代替子集:";
for(i=0;i<flag;i++)
{
if(part[i]!="")cout<<" i"<<part[i]<<"},";
}
cout<<endl<<"则DFA最小化后的各边信息如下: "<<endl;
char letters[max];
char letter='A';
for(i=0;i<flag;i++)
{
if(part[i]!="")
{
letters[i]=letter;
++letter;
}
}
for(i=0;i<flag;i++)
for(j=0;j<Change.length();j++)
{
ss=move(part[i],Change[j],b);
if(part[i]!=""&&ss!="&")cout<<letters[i]<<" "<<Change[j]<<" ";
for(x=0;x<flag;x++)
if(isexist(ss.substr(0, 1),part[x]))cout<<letters[x]<<endl;
}
system("pause");
}