#include <iostream>
#include <stdio.h>
#include <cctype>
#include <stack>
#include <string>
#include <map>
#include <set>
#include <vector>
#include<iterator>
#include <fstream>
using namespace std;
/*构造NFA和DFA所需要的结构体*/
//NFA的节点
struct node
{
string nodeName;
};
//NFA的边
struct edge
{
node startName; //起始点
node endName; //目标点
char tranSymbol; //转换符号
};
//NFA的组成单元,一个大的NFA单元可以是由很多小单元通过规则拼接起来
struct elem
{
int edgeCount; //边数
edge edgeSet[100]; //该NFA拥有的边
node startName; //开始状态
node endName; //结束状态
};
// 定义 DFA 的状态
struct DFAState {
set<string> nfaStates; //一个包含NFA状态的集合
string stateName;
};
// 定义 DFA 的转换关系
struct DFATransition {
DFAState fromState;
DFAState toState;
char transitionSymbol;
};
int nodeNum = 0;
/*下面是转换为DFA的主要函数*/
// 计算 NFA 状态的ε闭包
DFAState eClosure(const set<string>& nfaStates,elem nfa) {
DFAState eClosureState;//存储计算出的ε闭包状态及其包含的NFA状态集合
eClosureState.nfaStates = nfaStates;
stack<string> stateStack;
// 初始化栈,将初始状态加入栈,最开始nfaState里只有NFA_Elem.startName
for (const string& nfaState_name : nfaStates) {
stateStack.push(nfaState_name);
}
while (!stateStack.empty()) {
string currentState = stateStack.top();
stateStack.pop();
// 遍历 NFA 的边
for (int i = 0; i < nfa.edgeCount; i++) {
edge currentEdge = nfa.edgeSet[i];
// 如果边的起始状态是当前状态,并且边的转换符号是#,那么将目标状态加入ε闭包
if (currentEdge.startName.nodeName == currentState && currentEdge.tranSymbol == '#') {
// 检查目标状态是否已经在ε闭包中,避免重复添加
if (eClosureState.nfaStates.find(currentEdge.endName.nodeName) == eClosureState.nfaStates.end()) {
eClosureState.nfaStates.insert(currentEdge.endName.nodeName);
// 将目标状态加入栈以便进一步处理
stateStack.push(currentEdge.endName.nodeName);
}
}
}
}
// 为ε闭包分配一个唯一的名称
for (const string& nfaState_name : eClosureState.nfaStates) {
eClosureState.stateName += nfaState_name;
}
return eClosureState;
}
//move函数
DFAState move(const DFAState& dfaState, char transitionSymbol,elem nfa) {
DFAState nextState;
// 遍历 DFAState 中的每个 NFA 状态
for (const string& nfaState_name : dfaState.nfaStates) {
// 在这里遍历所有 NFA 状态的边
for (int i = 0; i < nfa.edgeCount; i++) {
edge currentEdge = nfa.edgeSet[i];
// 如果边的起始状态是当前状态,且边的转换符号等于输入符号,将目标状
12-09