怎样用C++实现DFA(确定有穷自动机)?

rmryt 2004-10-24 11:58:29
现在给出一个正则表达式,可以构造一个NFA(不确定有穷自动机)。存贮在矩阵或者邻接图中。然后我再实现从NFA到DFA的转化,用的是子集构造算法,想必学过编译原理的应该知道。我成功的构造出了Dtran表,DFA也就差不多出来了。现在问题是,只能确定DFA的开始状态,无法让程序判断结束状态,那么这个DFA也就一点用处也没有。如何在构造DFA的过程中让其自己找到所有DFA的结束状态,请各位高手指教,尤其是学过编译的请帮帮忙。谢谢!
...全文
1883 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
wangyangcheng 2005-08-15
  • 打赏
  • 举报
回复
Mark
rmryt 2004-11-03
  • 打赏
  • 举报
回复
我也做了一个完整的从验证正则表达式到构建NFA到构建DFA再检验文件中的匹配字符串的程序。我当初太傻不该问这么一个问题,其实很简单是我自己没有理清头脑。不过加了三个原来编的头文件进来程序足足上了1000行,也够我头疼的了。

现在可以结帖子了。
wenxinfly 2004-10-29
  • 打赏
  • 举报
回复
我写了一个NFA到DFA的程序,请指教
#include "stdafx.h"
#include <vector>
#include <string>
#include <queue>
#include <iostream>

using namespace std;

struct Transform
{
friend class FA;
char state1;
char letter;
char state2;
bool operator!=(char ch);
friend istream& operator>>(istream& in,Transform& t);
};
struct ChangeTable
{
string state;
int flag;
vector<string> changestate;
};
bool Transform::operator!=(char ch)
{
return state1!=ch||letter!=ch||state2!=ch;
}
namespace std
{
istream& operator>>(istream& in,Transform& t)
{
return in>>t.state1>>t.letter>>t.state2;
}
}
class FA
{
private:
vector<char> state; //状态集
vector<char> table; //输入字母表
vector<Transform> fun; //状态变迁函数
char q0; //初态
vector<char> Z; //终态集
string GetChangeState(char state1,char table);
void RemoveRepeat(string &str); //消除重复元素
private:
vector<ChangeTable> changetable;
bool IsInChangeTable(string str);
int GetIndexofChangeTable(); //找出第一个flag为0的索引
int GetIndexofChangeTable(string str); //找出str 在表中的索引
void GetChangeTable();
void OutputChangeTable();
public:
// FA(){}
void Deterministic(FA &dfa);
void input();
void output();

};
void FA::RemoveRepeat(string &str)
{
string mid;
string::size_type idx;
string::iterator pos;
for(pos=str.begin();pos!=str.end();++pos)
{
idx=mid.find(*pos);
if(idx==string::npos)
mid+=*pos;
}
str=mid;
}
bool FA::IsInChangeTable(string str)
{
vector<ChangeTable>::iterator pos;
for(pos=changetable.begin();pos!=changetable.end();++pos)
if((*pos).state==str)
return 1;
return 0;
}
int FA::GetIndexofChangeTable()
{
int index;
for(index=0;index<changetable.size();++index)
if(changetable[index].flag==0)
return index;
return -1;
}
int FA::GetIndexofChangeTable(string str)
{
int index;
for(index=0;index<changetable.size();++index)
if(changetable[index].state==str)
return index;
return -1;
}
string FA::GetChangeState(char state1,char table)
{
string str;
vector<Transform>::iterator pos;
for(pos=fun.begin();pos!=fun.end();++pos)
if((*pos).state1==state1&&(*pos).letter==table)
str+=(*pos).state2;
RemoveRepeat(str);
return str;
}
void FA::input()
{
char ch;
Transform tran;
cout<<"input the set of state,ended with '#'"<<endl;
cin>>ch;
while(ch!='#')
{
state.push_back(ch);
cin>>ch;
}
cout<<"input the set of input's table,ended with '#'"<<endl;
cin>>ch;
while(ch!='#')
{
table.push_back(ch);
cin>>ch;
}

cout<<"input the transform of function,formation is state1 letter state1 "<<endl;
cout<<"ended with '# # #'"<<endl;
cin>>tran;
while(tran!='#')
{
fun.push_back(tran);
cin>>tran;
}
cout<<"input the state of Initlization table"<<endl;
cin>>q0;

cout<<"input the set of termination,ended with '#'"<<endl;
cin>>ch;
while(ch!='#')
{
Z.push_back(ch);
cin>>ch;
}
}
void FA::GetChangeTable()
{
ChangeTable ct,midct;
string str;
string mid;
queue<string> q;
vector<char>::iterator pos;
string::iterator p;
ct.state=string(1,q0); //从初始状态开始
ct.flag=0;
changetable.push_back(ct);
int index=GetIndexofChangeTable();
while(index!=-1)
{
changetable[index].flag=1;
str=changetable[index].state; //弹出状态

for(pos=table.begin();pos!=table.end();++pos) //每种输入状态
{
mid.erase();
for(p=str.begin();p!=str.end();++p) //每个状态的每个字符
{
mid+=GetChangeState(*p,*pos);
RemoveRepeat(mid);
}

changetable[index].changestate.push_back(mid);

if(!mid.empty()&&!IsInChangeTable(mid))
{
ct.state=mid;
ct.flag=0;
changetable.push_back(ct);
}
}

index=GetIndexofChangeTable();
}
}
void FA::OutputChangeTable()
{
vector<ChangeTable>::iterator pos;
for(pos=changetable.begin();pos!=changetable.end();++pos)
{ cout<<"{"<<(*pos).state<<"} ";
for(int i=0;i<(*pos).changestate.size();i++)
cout<<"{"<<(*pos).changestate[i]<<"} ";
cout<<endl;
}
}
void FA::Deterministic(FA &dfa)
{
GetChangeTable();
//OutputChangeTable(); //输出中间状态转换表
dfa.table=table;
int size=0;
while(size<changetable.size()) //求状态集
{
dfa.state.push_back('A'+size);
size++;
}
dfa.q0='A'; //求初态
Transform tran;
vector<string>::iterator pos;
vector<char>::iterator p;
for(int i=0;i<changetable.size();++i)
{
tran.state1='A'+i;
for(p=table.begin(),pos=changetable[i].changestate.begin();pos!=changetable[i].changestate.end();++pos,++p)
{
tran.letter=*p;
int index=GetIndexofChangeTable(*pos);
tran.state2='A'+index;
if(index!=-1)
dfa.fun.push_back(tran);
}
//下面来求终态集
string mid;
string str=changetable[i].state;
for(p=Z.begin();p!=Z.end();++p)
{
mid.erase();
mid+=*p;
}
int idx=str.find(mid);
if(idx!=string::npos)
dfa.Z.push_back('A'+i);
}


}
void FA::output()
{
vector<char>::iterator pos;
cout<<"M={Vn,Vt,F,q0,Z},其中:"<<endl;
cout<<"Vn={";
for(pos=state.begin();pos!=state.end()-1;++pos)
cout<<*pos<<",";
cout<<*pos<<"}"<<endl;
cout<<"Vt={";
for(pos=table.begin();pos!=table.end()-1;++pos)
cout<<*pos<<",";
cout<<*pos<<"}"<<endl;

cout<<"F is:"<<endl;
for(std::vector<Transform>::iterator p=fun.begin();p!=fun.end();++p)
cout<<"f("<<(*p).state1<<","<<(*p).letter<<")="<<(*p).state2<<endl;

cout<<"q0="<<q0<<endl;

cout<<"Z={";
for(pos=Z.begin();pos!=Z.end()-1;++pos)
cout<<*pos<<",";
cout<<*pos<<"}"<<endl;

}
int main(int argc, char* argv[])
{
FA nfa,dfa;
nfa.input();
nfa.output();
nfa.Deterministic(dfa);
cout<<"转换成DFA为:"<<endl;
dfa.output();
return 0;
}
rmryt 2004-10-26
  • 打赏
  • 举报
回复
DFA可以实现,但是用来检测一个正则表达式需要知道DFA所有的终结状态啊。不然怎么判断当一个正则式全部读完时有没有落在DFA的结束状态上。也许首先就必须知道NFA的全部终结状态。可是从来没有听说过什么有效的算法。
SolarisX 2004-10-26
  • 打赏
  • 举报
回复
cause DFA means that in any q from Q for every terminal in alphabet there is and only one next state to enter ,so I think the simplest Switch/case statements can realize a DFA, I have tried one and succeeded. Your DFA maybe be very complex?
1. 实验内容 每一个正规集都可以由一个状态数最少的DFA所识别,这个DFA是唯一的(不考虑同构的情况)。任意给定的一个DFA,根据以下算法设计一个C程序,将该DFA 化简为与之等价的最简DFA。 2. 实验设计分析 2.1 实验设计思路 根据实验指导书和书本上的相关知识,实现算法。 2.2 实验算法 (1)构造具有两个组的状态集合的初始划分I:接受状态组 F 和非接受状态组 Non-F。 (2)对I采用下面所述的过程来构造新的划分I-new. For I 中每个组G do Begin 当且仅当对任意输入符号a,状态s和读入a后转换到I的同一组中; /*最坏情况下,一个状态就可能成为一个组*/ 用所有新形成的小组集代替I-new中的G; end (3)如果I-new=I,令I-final=I,再执行第(4)步,否则令I=I=new,重复步骤(2)。 (4)在划分I-final的每个状态组中选一个状态作为该组的代表。这些代表构成了化简后的DFA M'状态。令s是一个代表状态,而且假设:在DFA M中,输入为a时有从s到t转换。令t所在组的代表是r,那么在M’中有一个从s到r的转换,标记为a。令包含s0的状态组的代表是M’的开始状态,并令M’的接受状态是那些属于F的状态所在组的代表。注意,I-final的每个组或者仅含F中的状态,或者不含F中的状态。 (5)如果M’含有死状态(即一个对所有输入符号都有刀自身的转换的非接受状态d),则从M’中去掉它;删除从开始状态不可到达的状态;取消从任何其他状态到死状态的转换。 。。。。。。

19,468

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 图形处理/算法
社区管理员
  • 图形处理/算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧