【编译原理】NFA转DFA(子集构造法)

前文回顾

【编译原理】正则表达式转NFA
 

算法

来自龙书第二版
在这里插入图片描述

C++实现

#include<iostream>
#include<string>
#include<cstring>
#include<vector>
#include<algorithm>
#define MAX_TRANS 100
using namespace std;

vector<char>characters;//输入字符集
int DFA_state_number=0;//DFA中状态数量
vector<vector<int>>transition(MAX_TRANS);//记录终态的名称变化(一对多)
int final_count=0;//终态数量
int trans_count=0;//transition大小

//得到的状态集合
struct States
{
   
    vector<int>jset;
};

//DFA状态转换关系
struct relation
{
   
    States* pre;
    char jchar;
    States* next;
};
//得到s闭包
void Eclosure(bigCell NFA,States *s)
{
   
    for(int i=0;i<s->jset.size();i++)
    {
   
        for(int j=0;j<NFA.count;j++)
        {
   
            if(NFA.edges[j].source.id==s->jset[i] && NFA.edges[j].symbol=='?')
            {
   
                s->jset.push_back(NFA.edges[j].target.id);
            }
        }
    }
}
//能够从状态集s出发通过字符tc转换到达的NFA状态集合,结果放在t中
void move(char tc,bigCell NFA,States* s,States* t)
{
   
    for(int i=0;i<s->jset.size();i++)
    {
   
        for(int j=0;j<NFA.count;j++)
        {
   
            if(NFA.edges[j].source.id==s->jset[i] && NFA.edges[j].symbol==tc)
                t->jset.push_back(NFA.edges[j].target.id);
        }
    }
}
//添加状态子集
bool add(vector<States*>allSet,States *newS)
{
   
    bool b=true
### 编译原理 NFA DFA 练习题及解答 #### 子集法将NFA换为DFA的过程详解 在编译原理课程中,子集法是一种常用的方法来实现从非确定有限状态自动机(NFA)到确定有限状态自动机(DFA)换。此过程涉及创建一个新的DFA,其中每个状态对应于原NFA的一个或多个可能的状态组合[^1]。 对于给定的正则表达式`a(b|ab)*`构建最小状态数目的DFA为例: - **初始步**:识别出该正则式的NFA模型,并标记起始节点作为E-closure(ε闭包),即考虑通过空串可达的所有位置。 - **扩展步**:基于当前已有的DFA状态集合S,针对输入字符表中的每一个符号c,计算所有属于S的状态经由读取c能够到达的新状态群组T;如果这个新产生的状态尚未存在于现有的DFA结构里,则将其加入并继续处理直至不再新增为止。 - **终止条件**:当遍历完所有的可能性之后,就完成了整个化流程得到最终版本的DFA图谱。 下面给出具体的例子说明如何应用上述理论完成一次完整的练习: 假设有一个简单的NFA如下所示: ```plaintext ε a b → q0 ——> q1 ——> q2 | | \_____/ ε ``` 这里q0是起点,q2既是接受态也是终点之一;存在两条路径可以从q1回到自己——一条经过'a'移过去另一条则是直接利用ε边自环. 按照子集构造算法执行步骤如下: 1. 计算初态Q0={q0}对应的ε-closure(Q0),结果发现它等于{q0,q1},因为可以通过ε移动访问这两个结点. 2. 对于新的超级状态{q0,q1}(记作A),分别考察遇到不同字母后的动作: - 当接收'a',会跳至下一个超级状态B={q1,q2}; - 接收'b'时保持不变仍在A内循环; 3. 随着探索深入我们又发现了另一个未被记录过的超级状态B,重复之前的操作直到无法找到更多未知区域为止... 4. 整理所得数据形成一张表格形式展示出来便于理解: | Current State (DFA) | Input Symbol 'a'|Input Symbol 'b'| |--| | A | B | A | | B | C | D | 5. 最终绘制出简化版的DFA图形表示方法即可结束本次实践环节的学习旅程. ```python def epsilon_closure(states, transitions): """Compute the epsilon closure of given states.""" stack = list(states) eclosure = set(stack) while stack: state = stack.pop() if ('', state) in transitions: for next_state in transitions[('', state)]: if next_state not in eclosure: eclosure.add(next_state) stack.append(next_state) return frozenset(eclosure) def move(states, symbol, transitions): """Find all reachable states from `states` on input `symbol`""" result = set() for s in states: key = (symbol, s) if key in transitions: result.update(transitions[key]) return frozenset(result) def subset_construction(nfa_states, nfa_transitions, alphabet): dfa_states = [] unprocessed_states = [epsilon_closure({nfa_states[0]}, nfa_transitions)] transition_table = {} while unprocessed_states: current_dfa_state = unprocessed_states.pop(0) dfa_states.append(current_dfa_state) for letter in alphabet: new_nfa_states = move(current_dfa_state, letter, nfa_transitions) new_dfa_state = epsilon_closure(new_nfa_states, nfa_transitions) if new_dfa_state and new_dfa_state not in dfa_states: unprocessed_states.append(new_dfa_state) transition_key = (current_dfa_state, letter) transition_table[transition_key] = new_dfa_state accepting_states = [ state for state in dfa_states if any(s in nfa_accepting_states for s in state) ] start_state = epsilon_closure({nfa_start_state}, nfa_transitions) return { "start": start_state, "accepts": accepting_states, "transitions": transition_table, "all_states": dfa_states } ```
评论 23
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值