编译原理-(NFA的确定化)NFA转换为等价的DFA




然而并没有看懂,只是转下这种高深莫测的东西

https://www.jianshu.com/p/361de32e432d

 

 

DFA和NFA组成定义

DFA构成:五元组(K,∑,f,S,Z)

    • K:所有状态的集合

    • ∑:所有可接受的输入符号的集合

    • f:转换函数,是K × ∑ → K 上的映射。就是一个状态读入某个输入符号之后所到达的下一个状态的规则

    • S:K中的初始状态(只有一个)

    • Z:K中的终态集合(多个)

NFA构成:五元组

    • K:所有状态的集合

    • ∑:所有可接受的输入符号的集合

    • f:转换函数,是K × ∑* → 2^k 上的映射(2^k表示k的幂级)。就是一个状态读入某个输入符号之后,可能达到多个状态 

    • S:K中的初始状态集合(多个

    • Z:K中的终态集合(多个)

       

状态转换图及状态转换矩阵

  • 例子

DFA M = ({S,U,V,Q},{a,b},f,S,{Q}),其中f定义为

f(S,a) = U,    f(U,a) = Q,   f(V,a) = U,    f(Q,a) = Q,

f(S,b) = V,    f(U,b) = V,   f(V,b) = Q,    f(Q,b) = Q    

  • 状态图

    • 初态:以箭头指向表示

    • 终态:以双圆圈表示

    • 状态转换:以有向弧表示

       

      微信公众号:JavaWeb架构师

  • 状态转换表(矩阵表示)

    • (,) → 值:(当前状态,输入符号) → 下一状态

    • 右侧0/10表示非终态,1表示终态

状态\符号

a

b

S

U

V

0

U

Q

V

0

V

U

Q

0

Q

Q

Q

1

 

closure和move

ε-closure(I):其中I是一个集合。表示I中每个状态经过任意条ε弧后,所能达到的状态的集合。

move(I,a):其中I是一个集合,a是一条弧。表示I中每个状态经过一条a弧后,所能达到的状态的集合。

例子

  •  

  • 微信公众号

A = ε-closure(0) = {0,1,2,4,7}

move(A,a) = {3,8}

  •  

等价转换规则

这里介绍 子集法,假设NFA N = (K,∑,f,K0,Kt),构造一个等价DFA M = (S,∑,D,S0,St)

步骤
1) 计算ε-closure(K0),取名T0
2)标记T0以处理,分别计算ε-closure(move(T0,∑的单个输入),取名Tx……Ty
3)标记已处理,对新的Tx-Ty重复第二步,直到不再产生新的Ti集合为止
4)按照123步的关系,确定所有的T集合之间的转换关系
5S0=[T0]St=含有NFA中的终态的那个T集合
6)画出状态图

例子

  •  

    微信公众号

  • 计算ε-closure(K0),取名T0K0只有一个0状态

T0 = ε-closure(0) = {0,1,2,4,7}

  • 分别计算ε-closure(move(T0,∑的单个输入),取名Tx……Ty

----------------------------------------------T0------------------------------------------------

Ti = ε-closure(move(T0,a))

move(T0,a) = {3,8}

T1 = {1,2,3,4,6,7,8}

 

Ti = ε-closure(move(T0,b))

move(T0,b) = {5}

T2 = {1,2,4,5,6,7}

  • 对新的Tx-Ty重复第二步,直到不再产生新的Ti集合为止(T1T2)

----------------------------------------------T1------------------------------------------------

T1 = {1,2,3,4,6,7,8}

 

Ti = ε-closure(move(T1,a))

move(T1,a) = {3,8}

Ti = T1

 

Ti = ε-closure(move(T1,b))

move(T1,b) = {5,9}

T3 = {1,2,4,5,6,7,9}

----------------------------------------------T2------------------------------------------------

 T2 = {1,2,4,5,6,7}

 

Ti = ε-closure(move(T2,a))

move(T2,a) = {3,8}

Ti = T1

 

Ti = ε-closure(move(T2,b))

move(T2,b) = {5}

Ti = T2

----------------------------------------------T3------------------------------------------------

T3 = {1,2,4,5,6,7,9}

 

Ti = ε-closure(move(T3,a))

move(T3,a) = {3,8}

Ti = T1

 

Ti = ε-closure(move(T3,b))

move(T3,b) = {5,10}

T4 = {1,2,4,5,6,7,10}

----------------------------------------------T4------------------------------------------------

T4 = {1,2,4,5,6,7,10}

 

Ti = ε-closure(move(T4,a))

move(T4,a) = {3,8}

Ti = T1

 

Ti = ε-closure(move(T4,b))

move(T4,b) = {5}

Ti = T2

  • 至此,所有状态求解已经完成

    • S = {T0,T1,T2,T3,T4}

    • S0 = T0

    • St = T4(T4中含有10)

    • ∑ = {a,b} (和NFA是一样的)

    • D

D(T0,a) = T1D(T0,b) = T2D(T1,a) = T1D(T1,b) = T3D(T2,a) = T1D(T2,b) = T2D(T3,a) = T1D(T3,b) = T4D(T4,a) = T1D(T4,b) = T2

T0,T1,T2,T3,T4分别对应到0,1,2,3,4,得到状态转换图如下所示

  •  



  •  

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用C++编写的NFA转换DFA代码示例: ``` #include <iostream> #include <vector> #include <set> #include <map> using namespace std; // 定义NFA结构体 struct NFA { int start_state; // 起始状态 vector<int> accept_states; // 接受状态 map<pair<int, char>, vector<int>> transitions; // 转换函数 }; // 定义DFA结构体 struct DFA { set<int> states; // 状态集合 int start_state; // 起始状态 set<int> accept_states; // 接受状态集合 map<pair<int, char>, int> transitions; // 转换函数 }; // 获取NFA中从state状态出发通过symbol转换可以到达的所有状态 vector<int> get_next_states(NFA nfa, int state, char symbol) { vector<int> next_states; if (nfa.transitions.count(make_pair(state, symbol))) { next_states = nfa.transitions[make_pair(state, symbol)]; } return next_states; } // 获取NFA中从state状态出发可以到达的所有状态 set<int> epsilon_closure(NFA nfa, int state) { set<int> closure; closure.insert(state); bool changed = true; while (changed) { changed = false; for (int s : closure) { vector<int> next_states = get_next_states(nfa, s, 'e'); for (int next_state : next_states) { if (closure.count(next_state) == 0) { closure.insert(next_state); changed = true; } } } } return closure; } // 将NFA转换DFA DFA nfa_to_dfa(NFA nfa) { DFA dfa; // 计算NFA的epsilon闭包 set<int> start_state = epsilon_closure(nfa, nfa.start_state); dfa.states.insert(1); dfa.start_state = 1; if (nfa.accept_states.count(nfa.start_state)) { dfa.accept_states.insert(1); } map<set<int>, int> dfa_state_map; dfa_state_map[start_state] = 1; int curr_dfa_state = 1; set<int> unmarked_dfa_states; unmarked_dfa_states.insert(1); while (!unmarked_dfa_states.empty()) { int dfa_state = *unmarked_dfa_states.begin(); unmarked_dfa_states.erase(unmarked_dfa_states.begin()); set<int> nfa_states = dfa_state_map.inverse[dfa_state]; for (char symbol = 'a'; symbol <= 'z'; symbol++) { set<int> next_states; for (int nfa_state : nfa_states) { set<int> next_nfa_states = epsilon_closure(nfa, nfa_state); for (int next_nfa_state : next_nfa_states) { vector<int> transitions = get_next_states(nfa, next_nfa_state, symbol); for (int transition : transitions) { next_states.insert(transition); } } } if (!next_states.empty()) { int next_dfa_state; if (dfa_state_map.count(next_states)) { next_dfa_state = dfa_state_map[next_states]; } else { curr_dfa_state++; dfa.states.insert(curr_dfa_state); next_dfa_state = curr_dfa_state; dfa_state_map[next_states] = next_dfa_state; if (nfa.accept_states.count(next_states)) { dfa.accept_states.insert(next_dfa_state); } unmarked_dfa_states.insert(next_dfa_state); } dfa.transitions[make_pair(dfa_state, symbol)] = next_dfa_state; } } } return dfa; } int main() { // 定义NFA NFA nfa; nfa.start_state = 0; nfa.accept_states = {2}; nfa.transitions[make_pair(0, 'a')] = {1}; nfa.transitions[make_pair(1, 'b')] = {2}; nfa.transitions[make_pair(0, 'e')] = {3}; nfa.transitions[make_pair(3, 'a')] = {4}; nfa.transitions[make_pair(4, 'b')] = {2}; // 将NFA转换DFA DFA dfa = nfa_to_dfa(nfa); // 输出DFA cout << "DFA states: "; for (int state : dfa.states) { cout << state << " "; } cout << endl; cout << "DFA start state: " << dfa.start_state << endl; cout << "DFA accept states: "; for (int state : dfa.accept_states) { cout << state << " "; } cout << endl; cout << "DFA transitions: " << endl; for (auto it : dfa.transitions) { cout << " " << it.first.first << " --" << it.first.second << "--> " << it.second << endl; } return 0; } ``` 该代码使用了C++ STL库中的容器类型,如vector、set和map等,以便更方便地实现算法逻辑。在主函数中,我们先定义了一个NFA,然后调用nfa_to_dfa函数将其转换DFA,并输出DFA的各项属性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值