用某种高级语言写出:
(1)将正规式变成NFA的算法;
(2)将NFA确定化的算法;
(3) DFA状态最少化的算法。
写完就完事了 , 没咋测试拉
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e2+5;
struct edge{
char value;
int to;
};
vector<edge> v[maxn<<2];
int id=0;
string s;
//-------------------------NFA---------------------------//
stack<int> st,ed,str;
void print_nfa(){
cout<<s<<"的NFA是:"<<endl;
for(int i=0;i<=id;++i){
for(auto it:v[i]){
cout<<i<<"--"<<it.value<<"->"<<it.to<<endl;
}
}
}
void connection(char ch){
int nst,nsst;
nst=st.top();
st.pop();
nsst=st.top();
if(ch!='@') v[nsst].push_back({ch,nst});
}
void run1(){// '('
ed.push(++id);//这个括号的结束节点
str.push('(');
}
void run2(){// ')'
int nst=st.top(),nsst;
int ned=ed.top();
v[nst].push_back({'^',ned});//'^'代表空串,先将最后一个字符产生的节点连接到结束节点
char ch=str.top();
while(ch!='('){//将括号内的连起来
connection(ch);
str.pop();
ch=str.top();
}
str.pop();
str.push('@');
//括号这个整体的占位符,因为处理括号时处理了这个整体与前面的连接,故跳过
ned=ed.top();
st.push(ned);//这样就可视括号整体为一个普通字符了
ed.pop();
}
void run3(){// '|'
int nst=st.top();
int ned=ed.top();
v[nst].push_back({'^',ned});
char ch=str.top();
while(ch!='(' && ch!='S'){//将'|'前的连接
connection(ch);
str.pop();
ch=str.top();
}
}
void run4(){// '*'
//有如a*或()*因为上述处理都视为a
int nst=st.top();
st.pop();
int nsst=st.top();
v[nst].push_back({'^',nsst});
v[nsst].push_back({'^',nst});
st.push(nst);
}
void run5(char c){// 普通字符
str.push(c);
st.push(++id);//是这个字符的结束,下一个字符的开始标记
}
void nfa(){
str.push('S');
st.push(id);//全串的开始为0,结束为1
ed.push(++id);
for(char c:s){
if(c=='(') run1();
else if(c==')') run2();
else if(c=='|') run3();
else if(c=='*') run4();
else run5(c);
}
char ch=str.top();
if(st.top()!=0) v[st.top()].push_back({'^',1});
//后面的开始即前串的结束,将其连接到结束标记1
while(ch!='S'){
connection(ch);
str.pop();
ch=str.top();
}
print_nfa();
}
//------------------------DFA--------------------------//
int did=0;
vector<edge> dfav[maxn<<2];//dfa下的图
struct node{
bool fg;//1表示还有终态,反之无
set<int> ns;//集合
};
unordered_map<int,node > mp;//dfa中的序号,序号包含的node集合
bool vis[maxn<<2];
bool svis[maxn<<2];
set<char> diff;//不同的字符
node bfs(set<int> u,char c){ //在原图中从u集合出发只能走c的集合
memset(vis,0,sizeof(vis));
queue<int> q;
for(auto t:u){
q.push(t);
}
set<int> tv;
bool bfg=0;
while(!q.empty()){
int tp=q.front();
q.pop();
for(auto it:v[tp]){
if(it.value!=c) continue;
else{
if(vis[it.to]==1) continue;
else {
vis[it.to]=1;
tv.insert(it.to);
if(c=='^') q.push(it.to);
if(it.to==1) bfg=1;//包含终态
}
}
}
}
return node{bfg,tv};
}
bool check(set<int> x,set<int> y){//比较两个集合的关系
//0:相同 1:不同
if((int)x.size()!=(int)y.size()) return 1;
set<int>::iterator ix,iy;
for(ix=x.begin(),iy=y.begin();ix!=x.end();++ix,++iy){
if(*ix!=*iy) return 1;
}
return 0;
}
node merge(node a,node b){//合并集合
node c;
if(a.fg || b.fg) c.fg=1;
c.ns.insert(a.ns.begin(),a.ns.end());
c.ns.insert(b.ns.begin(),b.ns.end());
return c;
}
void print_set(set<int> s){
cout<<"集合为:";
for(auto i:s){
cout<<i<<" ";
}
cout<<endl;
}
void print_dfa(){
cout<<"序号集合:"<<endl;
for(int i=0;i<=did;++i){
cout<<i<<" ";
if(mp[i].fg) cout<<"是终态,";
else cout<<"不是终态,";
print_set(mp[i].ns);
}
cout<<"DFA是:"<<endl;
for(int i=0;i<=did;++i){
for(auto it:dfav[i]){
cout<<i<<"--"<<it.value<<"->"<<it.to<<endl;
}
}
}
void dfa(){
set<int> nu;
node nd;
for(int i=0;i<=id;++i){
for(auto it:v[i]){
if(it.value!='^') diff.insert(it.value);
}
}
nu.insert(0);
nd=bfs(nu,'^');
mp[0]=nd;
queue<int> q;
q.push(0);
nu.clear(),svis[0]=1;
while(!q.empty()){
int tp=q.front();
q.pop();
set<int> tpset=mp[tp].ns;
for(char c:diff){//先走一个c再走一个空
node cnd=bfs(tpset,c);
node knd=bfs(cnd.ns,'^');
knd=merge(cnd,knd);
if(!knd.ns.size()) continue; //空集out
bool type=check(tpset,knd.ns);//knd.ns:走出来的集合
//验证是否产生新集合 0:相同,1:不同
bool ffg=0;
for(auto it:mp){
if(!check(it.second.ns,knd.ns)){//与以前的集合相同
dfav[tp].push_back({c,it.first});
ffg=1;
break;
}
}
if(ffg) continue;
//产生了新的集合
mp[++did]=knd;
dfav[tp].push_back({c,did});
q.push(did);
}
}
print_dfa();
}
//------------------------Min_DFA--------------------------//
vector<edge> miv[maxn<<2];
int fa[maxn<<2];
vector<set<int> >setv;
unordered_map<char,int> myhash;//字符映射
int charnum;
int matrix[maxn<<1][maxn<<1];//变换矩阵
void init(){
setv.clear();
charnum=-1;
for(char c:diff) myhash[c]=++charnum; //字符映射为数字 构造变换矩阵
for(int i=0;i<=did;++i){
for(int j=0;j<=charnum;++j) matrix[i][j]=-1;
}
for(int i=0;i<=did;++i){
for(auto it:dfav[i]){
matrix[i][myhash[it.value]]=it.to;
}
}
}
int sec(int u){
return u==fa[u]?u:fa[u]=sec(fa[u]);
}
void unit(int x,int y){
x=sec(x),y=sec(y);
if(x==y) return;
fa[y]=x;
}
void unitset(set<int> s){//合并集合
for(auto i:s) fa[i]=i;
set<int>::iterator it;
for(it=s.begin();it!=s.end();++it){
if(it!=s.begin()){
int a=*it,b=*(--it);
++it;
unit(a,b);
}
}
}
pair<bool,vector<set<int> > > divide(set<int> ns,char c){//根据c来划分子集
//1:不可拆分 0可拆分,则返回一个集合簇
set<int> allfa;
vector<set<int> > res;
bool fg=0;
for(int i:ns){
if(matrix[i][myhash[c]]==-1) allfa.insert(-1),fg=1;
else allfa.insert(sec(i));
}
if(allfa.size()==1) return make_pair(1,res);
if(fg){ //-1,即没有c,单独考虑
set<int> newset;
for(int i:ns){
if(matrix[i][myhash[c]]==-1) newset.insert(i);
}
res.push_back(newset);
}
for(auto nfa:allfa){
if(nfa==-1) continue;
set<int> newset;
for(int i:ns){
if(sec(matrix[i][myhash[c]])==nfa) newset.insert(i);
}
res.push_back(newset);
}
for(auto nset:res) unitset(nset);//分子集之后,重新单独合并
return make_pair(0,res);
}
pair<bool,vector<set<int> > > check(set<int> ns){//检验每个集合变化状态是否相同
//1:可视为一整体 0需要拆分,则返回一个集合簇
vector<set<int> > res,run;
if(ns.size()==1){//单个元素无法拆分
return make_pair(1,res);
}
set<int>::iterator it;
run.push_back(ns);
bool allflag=1;
while( (int)run.size()!=0 ){//直到每个子集都不可划分
bool fg=0;
vector<set<int> > tp;
for(auto nset:run){
bool nsetflag=1;
for(char c:diff){
pair<bool,vector<set<int> > > p= divide(nset,c);
if(p.first==0){
allflag=0;
nsetflag=0;
tp.insert(tp.end(),p.second.begin(),p.second.end());
break;
}
}
if(nsetflag){//说明这个子集暂时不可拆分了
res.push_back(nset);
}
}
run=tp;
}
return make_pair(allflag,res);
}
void min_dfa(){//对dfav进行最小化
//vector<int> dfav[] 记录了图
//map<int,node> mp 记录了点的信息
init();//初始化
set<int> end_state,initial_state;
for(auto it:mp){
if(it.second.fg){//终态
end_state.insert(it.first);
}
else initial_state.insert(it.first);//初态
}
unitset(initial_state);
unitset(end_state);
setv.push_back(end_state);
setv.push_back(initial_state);
while(1){
bool flag=1;
vector<set<int> > tp;
for(auto nset:setv){
pair<bool,vector<set<int> > > np=check(nset);
if(np.first==0) flag=0;
tp.insert(tp.end(),np.second.begin(),np.second.end());
}
setv=tp;
if(flag) break;//已经全都不可拆分
}
//构图
for(auto nset:setv){//每个集合选一个代表
char rep=sec(*(nset.begin()));
for(auto c:diff){
if(matrix[rep][myhash[c]]==-1) continue;
miv[rep].push_back({c,sec(matrix[rep][myhash[c]])});
}
}
}
int main(){
cout<<"输入正规式:";
cin>>s;
nfa();
dfa();
min_dfa();
return 0;
}
/*
输入正规式:a|b*
a|b*的NFA是:
0--a->2
0--^->3
0--b->3
2--^->1
3--^->0
3--^->1
序号集合:
0 是终态,集合为:0 1 3
1 是终态,集合为:1 2
DFA是:
0--a->1
0--b->0
*/