实验一利用子集法构造DFA.docx
《实验一利用子集法构造DFA.docx》由会员分享,可在线阅读,更多相关《实验一利用子集法构造DFA.docx(42页珍藏版)》请在冰豆网上搜索。
![实验一利用子集法构造DFA.docx](https://file1.bdocx.com/fileroot1/2022-11/30/95ff5bc8-9ff7-4688-8e71-cc90ce97156f/95ff5bc8-9ff7-4688-8e71-cc90ce97156f1.gif)
实验一利用子集法构造DFA
实验一利用子集法构造DFA
一、实验目的
掌握将非确定有限自动机确定化的方法和过程
2、实验要求及内容
实验要求:
1.输入一个NFA,输出一个接受同一正规集的DFA;
2.采用C++语言,实现该算法;
3.编制测试程序;
4.调试程序。
实验步骤:
1.输入一个NFA关系图;
2.通过一个转换算法将NFA转换为DFA;
3.显示DFA关系图。
三、实验环境
计算机、Windows操作系统、VisualC++程序集成环境。
4、程序代码
#include"stdafx.h"
#include
#include
#include
#include
#include
usingnamespacestd;
structedge{
intstart,end;
charc;
}
E[100],Ekong[100];//E保存所有的边,Ekong保存转换字符为空的边
structState{
intH[100];//状态集合
intcount;//状态集合中的元素个数
intflag;//是否是接受状态
intmark;//状态编号
};
intn;//n:
边数
intnk=0;//空字符转换的边数
intfirst,accept;//开始状态,接受状态
charalpha[100];//输入字母表,#代表空串
intnumof_char=0;//字母表中的字符个数
intuseof_char[256];//该转换字符是否用过
intf[200];//状态属性标志:
0表示始态,1表示接受态,-1表示中间态
StateDFA[100];//DFA状态集
intuseof_DFA[100];//标志构造出来的状态是否已存在
intnumof_Dtran=0;//最后得到的DFA中的状态数
charDtran[100][100];//DFA状态转换表
voidinput()
{
inti,s,e;
charch;
cout<<"请输入转换的有向边数n:
"<cin>>n;
cout<<"请输入NFA的开始状态:
"<cin>>first;
cout<<"请输入NFA的接受状态(输入-1结束):
"<memset(f,-1,sizeof(f));
memset(useof_char,0,sizeof(useof_char));
f[first]=0;
cin>>accept;
while(accept!
=-1)
{
f[accept]=1;
cin>>accept;
}
cout<<"请输入NFA,起点,终点,转换字符('#'表示空字符):
"<intk=0;
for(i=0;i{
cin>>s>>e>>ch;
E[i].start=s;
E[i].end=e;
E[i].c=ch;
if(ch!
='#'&&!
useof_char[ch])
{
alpha[numof_char++]=ch;
useof_char[ch]=1;
}
if(ch=='#')
{
Ekong[nk].start=s;
Ekong[nk].end=e;
Ekong[nk].c=ch;
nk++;
}
}
}
Statemove(StateT,chars)//c!
='#'
{
Statetemp;
temp.count=0;
temp.mark=T.mark;
inti,j=0,k=0;
for(i=0;i{
j=0;
while(j{
if(E[j].start==T.H[i]&&E[j].c==s)
{temp.H[temp.count++]=E[j].end;
}
j++;
}
}
returntemp;
}
voidarriveBynone(intt,intresult[],int&num)//搜索状态t通过一个或多个空字符到达的状态,结果存在result中
{
intk=0;
intm=0;
num=0;
stackS;
S.push(t);
intj;
while(!
S.empty())
{
j=S.top();
S.pop();
m=0;
while(m{
if(Ekong[m].start==j)
{
result[num++]=Ekong[m].end;
S.push(Ekong[m].end);
}
m++;
}
}
}
boolcheck(inti,StateT)//判断状态i是否在T中
{
intj;
for(j=0;j{
if(T.H[j]==i)
returntrue;
}
returnfalse;
}
Stateclosure(StateT)//求闭包
{
stackSTACK;
Statetemp;
inti,j,k;
for(i=0;i{
STACK.push(T.H[i]);
temp.H[i]=T.H[i];
}
temp.count=T.count;
temp.mark=T.mark;
while(!
STACK.empty())
{
intt=STACK.top();
STACK.pop();
//搜索状态t通过一个或多个空字符到达的状态
intsearch_result[100];
intnum;
arriveBynone(t,search_result,num);
for(j=0;j{
if(!
check(search_result[j],temp))
{
temp.H[temp.count++]=search_result[j];
STACK.push(search_result[j]);
}
}
}
for(k=0;k{
if(f[temp.H[k]]==1)
{
temp.flag=1;
break;
}
if(f[temp.H[k]]==0)
{
temp.flag=0;
break;
}
}
sort(temp.H,temp.H+temp.count);
for(i=0;i{
if(temp.count!
=DFA[i].count)
continue;
sort(DFA[i].H,DFA[i].H+DFA[i].count);
for(j=0;j{
if(DFA[i].H[j]!
=temp.H[j])
break;
}
if(j>=DFA[i].count)
temp.mark=DFA[i].mark;
}
returntemp;
}
intcheck_inDFA()//检查DFA中是否存在未被标记的状态,有则返回标号,否则返回-1
{
inti;
for(i=0;i{
if(!
useof_DFA[i])
returni;
}
return-1;
}
boolcheck_whetherin_DFA(StateT)
{
inti,j;
sort(T.H,T.H+T.count);
for(i=0;i{
if(T.count!
=DFA[i].count)
continue;
sort(DFA[i].H,DFA[i].H+DFA[i].count);
for(j=0;j{
if(DFA[i].H[j]!
=T.H[j])
break;
}
if(j>=DFA[i].count)
returntrue;
}
if(i>=numof_Dtran)
returnfalse;
else
returntrue;
}
voidchild_method()
{
intm,n;
for(m=0;m<100;m++)
for(n=0;n<100;n++)
Dtran[m][n]='#';
for(m=0;m<100;m++)
DFA[m].flag=-1;
StateS0,U;
S0.flag=0;
S0.count=1;
S0.H[0]=first;
StateT;
T=closure(S0);
T.mark=0;
T.flag=0;
DFA[numof_Dtran++]=T;
memset(useof_DFA,0,sizeof(useof_DFA));
intj=check_inDFA();
intk;
while(j!
=-1)
{
useof_DFA[j]=1;
for(k=0;k{
U=closure(move(DFA[j],alpha[k]));
//ifU不在DFA中
if(!
check_whetherin_DFA(U))
{U.mark=numof_Dtran;
DFA[numof_Dtran++]=U;
}
Dtran[DFA[j].mark][U.mark]=alpha[k];
}
j=check_inDFA();
}
}
voidprint()
{
inti,j;
for(i=0;i{
cout<
";
for(j=0;jcout<if(DFA[i].flag==1)
cout<<"此为DFA的接受状态";
if(DFA[i].flag==0)
cout<<"此为DFA的开始状态";
cout<}
cout<for(i=0;i{
for(j=0;j{if(Dtran[i][j]!
='#')
{cout<"<}
}
}
}
voidjudge(stringch)
{
inti,j,k;
intnum=ch.length();
Statetemp;
k=0;
for(i=0;i{
for(j=0;j{
if(Dtran[k][j]==alpha[i])
{
temp=DFA[j];
k=j;
break;
}
}
}
if(temp.flag!
=1)
cout<<"字符串"<else
cout<<"字符串"<cout<}
int_tmain(intargc,_TCHAR*argv[])
{
input();
child_method();
cout<print();
strings;
while(cin>>s)
judge(s);
system("pause");
return0;
}
5、实验结果
6、算法分析
使用子集构造法对非确定有限自动机进行确定化的过程中存在大量重复计算的问题。
为解决此问题,基于非确定有限自动机的特点并针对子集构造法的不足,提出了一种优化的非确定有限自动机确定化算法。
首先定义了识别符的有效引出状态集概念并证明了ε-closure的并定理以保证算法的正确性,其次给出了用于避免重复计算的识别符的有效引出状态集的构造子算法和单状态集的ε-closure的求算子算法,基于这两个子算法给出了优化的非确定有限自动机确定化算法,最后将算法应用于实例,实验结果表明计算量远小于子集构造法的计算量。
相比子集构造法,算法能更有效地对非确定有限自动机进行确定化。
七、实验小结
以前上课时有许多的问题并没有真正的认识到,但通过这次实验,使我掌握了许多更重要的知识点。
通过实验,我们可以知道将NFA转换成接受同样语言的DFA的算法称为子集构造算法。
NFA变换到DFA的基本思想是:
让DFA的每个状态对应NFA的一个状态集。
实验实现了NFA到DFA的转换。
实验二THOMPSON算法的实现
一、实验目的
掌握将正规表达式转换为NFA的方法和过程
3、实验要求及内容
1.输入一个正规表达式,输出一个接受同一语言的NFA
2.采用C++语言,实现该算法
3.编制测试程序
4.调试程序
三、实验环境
计算机、Windows操作系统、VisualC++程序集成环境。
四、程序代码
#include"Thompson.h"
voidmain()
{
stringRegular_Expression="(a|b)*abb";
cellNFA_Cell;
input(Regular_Expression);//调试需要先屏蔽
Regular_Expression=add_join_symbol(Regular_Expression);
Regular_Expression=postfix(Regular_Expression);
NFA_Cell=express_2_NFA(Regular_Expression);
Display(NFA_Cell);
}
cellexpress_2_NFA(stringexpression)
{
intlength=expression.size();
charelement;
cellCell,Left,Right;
stackSTACK; |
for(inti=0;i{
element=expression.at(i);
switch(element)
{
case'|':
Right=STACK.top();
STACK.pop();
Left=STACK.top();
STACK.pop();
Cell=do_Unite(Left,Right);
STACK.push(Cell);
break;
case'*':
Left=STACK.top();
STACK.pop();
Cell=do_Star(Left);
STACK.push(Cell);
break;
case'+':
Right=STACK.top();
STACK.pop();
Left=STACK.top();
STACK.pop();
Cell=do_Join(Left,Right);
STACK.push(Cell);
break;
default:
Cell=do_Cell(element);
STACK.push(Cell);
}
}
cout<<"处理完毕!
"<Cell=STACK.top();
STACK.pop();
returnCell;
}
celldo_Unite(cellLeft,cellRight)
{
cellNewCell;
NewCell.EdgeCount=0;
edgeEdge1,Edge2,Edge3,Edge4;
stateStartState=new_StateNode();
stateEndState=new_StateNode();
Edge1.StartState=StartState;
Edge1.EndState=Left.EdgeSet[0].StartState;
Edge1.TransSymbol='#';
Edge2.StartState=StartState;
Edge2.EndState=Right.EdgeSet[0].StartState;
Edge2.TransSymbol='#';
Edge3.StartState=Left.EdgeSet[Left.EdgeCount-1].EndState;
Edge3.EndState=EndState;
Edge3.TransSymbol='#';
Edge4.StartState=Right.EdgeSet[Right.EdgeCount-1].EndState;
Edge4.EndState=EndState;
Edge4.TransSymbol='#';
//先将Left和Right的EdgeSet复制到NewCell
cell_EdgeSet_Copy(NewCell,Left);
cell_EdgeSet_Copy(NewCell,Right);
//将新构建的四条边加入EdgeSet
NewCell.EdgeSet[NewCell.EdgeCount++]=Edge1;
NewCell.EdgeSet[NewCell.EdgeCount++]=Edge2;
NewCell.EdgeSet[NewCell.EdgeCount++]=Edge3;
NewCell.EdgeSet[NewCell.EdgeCount++]=Edge4;
//构建NewCell的启示状态和结束状态
NewCell.StartState=StartState;
NewCell.EndState=EndState;
returnNewCell;
}
//处理ab
celldo_Join(cellLeft,cellRight)
{
for(inti=0;i{
if(Right.EdgeSet[i].StartState.StateNpare(Right.StartState.StateName)==0)
{
Right.EdgeSet[i].StartState=Left.EndState;
STATE_NUM--;
}
elseif(Right.EdgeSet[i].EndState.StateNpare(Right.StartState.StateName)==0)
{
Right.EdgeSet[i].EndState=Left.EndState;
STATE_NUM--;
}
}
Right.StartState=Left.EndState;
cell_EdgeSet_Copy(Left,Right);
Left.EndState=Right.EndState;
returnLeft;
}
celldo_Star(cellCell)
{
cellNewCell;
NewCell.EdgeCount=0;
edgeEdge1,Edge2,Edge3,Edge4;
stateStartState=new_StateNode();
stateEndState=new_StateNode();
//构建边
Edge1.StartState=StartState;
Edge1.EndState=EndState;
Edge1.TransSymbol='#';
Edge2.StartState=Cell.EndState;
Edge2.EndState=Cell.StartState;
Edge2.TransSymbol='#';
Edge3.StartState=StartState;
Edge3.EndState=Cell.StartState;
Edge3.TransSymbol='#';
Edge4.StartState=Cell.EndState;
Edge4.EndState=EndState;
Edge4.TransSymbol='#';
//构建单元
cell_EdgeSet_Copy(NewCell,Cell);
NewCell.EdgeSet[NewCell.EdgeCount++]=Edge1;
NewCell.EdgeSet[NewCell.EdgeCount++]=Edge2;
NewCell.EdgeSet[NewCell.EdgeCount++]=Edge3;
NewCell.EdgeSet[NewCell.EdgeCount++]=Edge4;
NewCell.StartState=StartState;
NewCell.EndState=EndState;
returnNewCell;
}
celldo_Cell(charelement)
{
cellNewCell;
NewCell.EdgeCount=0;
edgeNewEdge;
stateStartState=new_StateNode();
stateEndState=new_StateNode();
NewEdge.StartState=StartState;
NewEdge.EndState=EndState;
NewEdge.TransSymbol=element;
NewCell.EdgeSet[NewCell.EdgeCount++]=NewEdge;
NewCell.StartState=NewCell.EdgeSet[0].StartState;
NewCell.EndState=NewCell.EdgeSet[0].EndState;//EdgeCount此时为1
returnNewCell;
}
voidcell_EdgeSet_Copy(cell