前文回顾
【编译原理】正则表达式转NFA
【编译原理】NFA转DFA(子集构造法)
C++实现
#include <iostream>
#include <fstream>
#include <string>
#include <stack>
#include <stdlib.h>
#include <algorithm>
using namespace std;
//更新token的终态编号
void finalStateTrans(vector<Token>&tokens)
{
//将新增终态加入token终态集
for(int i=0; i<tokens.size(); i++)
{
for(int j=0; j<trans_count; j++)
{
int len=transition[j].size();
for(int k=0; k<len; k++)
{
if(tokens[i].finalState[0]==transition[j][k] && transition[j][k]!=0)
{
tokens[i].finalState.push_back(j);
}
}
}
}
//删除最开始的终态
for(int i=0; i<tokens.size(); i++)
{
//cout<<tokens[i].name<<" ";
tokens[i].finalState.erase(tokens[i].finalState.begin());
// for(int j=0;j<tokens[i].finalState.size();j++)
// {
// cout<<tokens[i].finalState[j]<<" ";
// }
// cout<<endl;
}
}
//最小化DFA
vector<vector<int>> minDFA(vector<vector<int>>dfaT,int *accepted,vector<Token>&tokens)
{
finalStateTrans(tokens);
//可接受状态个数
int accl=final_count;
//不可接受状态子集号为1
//如果是可接受状态,则子集号为2
vector<int>subset(DFA_state_number+1,1);
subset[0]=0;
for(int i=1; i<=DFA_state_number; i++)
{
if((find(accepted,accepted+accl,i)-accepted)!=final_count)
{
subset[i]=2;//状态i的子集号为2
}
//cout<<i<<" "<<subset[i]<<endl;
}
//记录状态i的子集号是否需要修改
int changed[DFA_state_number+1];
for(int i=1; i<=DFA_state_number; i++)
changed[i]=0;
//第一轮子集号修改
int chl=characters.size();
for(int i=1; i<DFA_state_number; i++)
{
bool need_change=false;
for(int j=0; j<chl; j++)
{
char c=characters[j];
int next_state1=dfaT[i][c];//状态i通过c转换的下一状态
int next_state2=dfaT[i+1][c];//状态i+1通过c转换的下一状态
//cout<<next_state1<<next_state2<<endl;
//如果两状态在同一子集,但其下一状态不在,则子集号需要修改
if(subset[next_state1]!=subset[next_state2] && subset[i]==subset[i+1])
{
need_change=true;
changed[i+1]=1;
break;
}
}
if(need_change==true)
break;
}
//找到需要修改的子集号
while(find(changed,changed+DFA_state_number+1,1)!=changed+DFA_state_number+1)
{
//需要修改的后面所有状态子集号+1
int curr=find(changed,changed+DFA_state_number+1,1)-changed;
for(int i=curr; i<=DFA_state_number; i++)
{
subset[i]++;
}
changed[curr]=0;//恢复
//下一轮子集号修改
for(int i=1; i<DFA_state_number; i++)
{
bool need_change=false;
for(int j=0; j<chl; j++)
{
char c=characters[j];
int next_state1=dfaT[i][c];//状态i通过c转换的下一状态
int next_state2=dfaT[i+1][c];//状态i+1通过c转换的下一状态
//如果两状态在同一子集,但其下一状态不在,则子集号需要修改
if(subset[next_state1]!=subset[next_state2] && subset[i]==subset[i+1])
{
need_change=true;
changed[i+1]=1;
break;
}
}
if(need_change==true)
break;
}
}
//合并等价状态,更新dfaT
int minStateCount=subset[DFA_state_number];//子集数量,即最小化DFA中状态的数量
vector<vector<int>>minDFAT(MAX,vector<int>(MAX));
//i遍历所有子集
for(int i=1; i<=minStateCount; i++)
{
//j遍历子集中所有状态
for(int j=1; j<=DFA_state_number; j++)
{
//cout<<j<<" "<<subset[j]<<endl;//输出状态及区号
if(subset[j]==i)
{
//k遍历字符集
for(int k=0; k<chl; k++)
{
char c=characters[k];
int temp=dfaT[j][c];
if(temp!=0)//下一状态不为空,则更新dfa
minDFAT[i][c]=subset[temp];
}
}
}
}
//更新token的终态,用区号代替状态号
for(int i=0; i<tokens.size(); i++)
{
int len=tokens[i].finalState.size();
for(int j=0;j<len;j++)
{
int oldState=tokens[i].finalState[j];
replace(tokens[i].finalState.begin(),tokens[i].finalState.end(),oldState,subset[oldState]);
}
//去除终态集重复元素
sort(tokens[i].finalState.begin(),tokens[i].finalState.end());
tokens[i].finalState.erase(unique(tokens[i].finalState.begin(), tokens[i].finalState.end()), tokens[i].finalState.end());
}
cout<<"最小化后DFA信息:"<<endl;
for(int i=1; i<=minStateCount; i++)
{
for(int k=0; k<chl; k++)
{
char c=characters[k];
if(minDFAT[i][c]!=0)
cout<<i<<" "<<c<<" "<<minDFAT[i][c]<<endl;
}
}
cout<<endl;
return minDFAT;
}
//显示token信息
int showToken(vector<Token>tokens)
{
cout<<"各token的终态集:"<<endl;
for(int i=0; i<tokens.size(); i++)
{
cout<<tokens[i].name<<":";
int len=tokens[i].finalState.size();
for(int j=0;j<len;j++)
{
cout<<tokens[i].finalState[j]<<" ";
}
cout<<endl;
}
}