本文将以两种方法实现NFA转DFA,并利用C语言实现。

方法二已利用HNU OJ系统验证,方法一迷之WA,但思路应该是对的,自试方案,测试均通过。

(主要是思路,AC均浮云,大概又有什么奇怪的Case没想到)

==========================================================

下面的描述以机械工业出版社的《计算理论导引》的第三版35页图为例。该NFA如下图。

  • 思路一:穷举组合状态,构造DFA

    该思路接近《计算理论》课本35页思路。

    • 新DFA的状态数

      为了能够保存NFA的各种不确定状态,DFA利用更多的状态来模拟保存。假设NFA有N个状态,那么每一个状态都有到达和没有到达两种可能,也就是新的DFA有2^N个新的状态。例如当我们到达上图中的状态1时,由于存在空漂移,那么我们可能到达了3状态,也就是新DFA状态中的101(5)号状态。
    • 核心思路

      先把这种思路的核心代码放在下面:

      /**
      *Param int CurrState 当前需要查找转移状态的当前状态
      *Param int *NextStateArray 在当前输入情况下的NFA的状态转移表
      *Param int NFA_size NFA的大小
      */
      int find_next(int CurrState,int* NextStateArray,int NFA_size){
      int NextState = 0,i = 0,NFAState = 0;
      for(i = NFA_size-1; i>=0;i--){
      NFAState = CurrState/(1<<i);
      CurrState -= NFAState * (1<<i);
      if(NFAState == 1) NextState = NextState|NextStateArray[i];
      //若CurrState中对应的NFA状态为1,就去NFA转移表中找到该状态的下一个状态
      //并将这些状态添加到DFA的下一个状态中去
      }
      return NextState;
      }

      这段代码展现的是思路一、二均使用的核心。以上文提到过的5号(101)状态来举例。

      currstate = 5(101)的find_next过程

      状态号为5(101)代表着该状态包含了原NFA中的状态3和状态1

      假设当前输入为0,则传到find_next的参数为转移表中0的那一列:0(000) 6(110) 5(101)

      循环中依次访问了101包含的NFA1号状态中的下态(000)和3号状态的下态(101)

      通过位或添加到了DFA当前状态的下一个状态中。

      当遍历完所有currstate包含的NFA状态,返回统计好的下一状态(101)

      find_next函数就是通过这样的方法,对新的DFA中的一个状态在一种输入情况下的状态转移计算出来。获取完整的DFA状态转移,只需要对新的DFA中的所有状态均执行这个过程。(但是这样也就没有考虑一些不可能到达的状态,或可以通过建立后修建得到)

  • 思路二

    思路二接着刚才的思路一,若我们转成的DFA中有很多很多没有可能到达的状态怎么办?何不逆向考虑,我们从DFA的起始状态开始,推算其有可能达到的DFA状态,判断该状态是否生成。若没有生成,再生成这个DFA新状态。

    下面用伪代码来形式化这一个过程。

    • 核心思路

      function define_DFA_state (int currstate)
      for currstate 中的每一个包含的NFA状态
      currstate 的0输入转移 = 这些NFA状态的0输入转移取位或(思路同find_next)
      currstate 的1输入转移 = 这些NFA状态的1输入转移取位或
      end for
      //这里就完成了currstate的转移定义
      if currstate 的0输入转移未被定义 define_DFA_state 这个状态
      if currstate 的1输入转移未被定义 define_DFA_state 这个状态
      //这样就圆满了,能转移走到的都定义了
      end function
    • 注意

      这种思路带来的后果是DFA并不是按照0,1,2,3这样排序好的状态,生成状态表的时候可能会顺序比较混乱。记得在代码中重新给状态编号,来更清楚生成状态转移表。

计算理论:NFA转DFA的两种方法的更多相关文章

  1. 用for循环计算(1-3+5-7...99)的结果(两种方法)

    1) sum=0 count=1 for i in range(1,100,2): if count % 2==0: sum = sum - i else: sum = sum + i count = ...

  2. 用Python计算幂的两种方法,非递归和递归法

    用Python计算幂的两种方法: #coding:utf-8 #计算幂的两种方法.py #1.常规方法利用函数 #不使用递归计算幂的方法 """ def power(x, ...

  3. 智能手机的耗电特征及APP耗电量测试的两种方法

    文章陈述了手机发展趋势及耗电特性,集中讨论了时下最为关心的智能手机耗电问题,并介绍了测量手机软件耗电量的两种方法.此外还解释了为何运营商此前会提出收取微信的费用,心跳机制是什么. 美国著名手机公司Pa ...

  4. Redis中持久化的两种方法详解

    Redis提供了两种不同的持久化方法来将数据存储到硬盘里面.一种方法叫快照(snapshotting),它可以将存在于某一时刻的所有数据都写入硬盘里;另一种方法教只追加文件(append-only f ...

  5. 在shell script中进行数值运算的两种方法

    方法1:使用"$((计算式))"的方式进行数值运算,不需要使用declare命令显示声明数值型变量来存储计算结果: 方法2:使用declare命令配合"-i"选 ...

  6. 2014 Super Training #4 G What day is that day? --两种方法

    原题: ZOJ 3785 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3785 题意:当天是星期六,问经过1^1+2^2+ ...

  7. BW增强数据源的两种方法

    BW增强数据源的两种方法 2009-04-01, by SAPBI 前言:我们经常会遇到系统标准的数据源,或者我们自建的数据源无法满足要求的情况,这个时候在数据源中添加几个相关的字段,可能就能满足我们 ...

  8. WPF多线程UI更新——两种方法

    WPF多线程UI更新——两种方法 前言 在WPF中,在使用多线程在后台进行计算限制的异步操作的时候,如果在后台线程中对UI进行了修改,则会出现一个错误:(调用线程无法访问此对象,因为另一个线程拥有该对 ...

  9. PMP知识点(二)——三点估算的两种方法对活动持续时间估算的影响和如何取舍

    一.准备工作 活动持续时间的估算属于PMBOK中第六章项目时间管理中第五节6.6估算活动持续时间的内容. 三点估算是6.5和7.2(估算成本)中应用到的一种工具和技术.数据流向图参考如下: 其应用到的 ...

随机推荐

  1. Ubuntu超好用软件:剪贴板

    这个软件的作用就是保存你复制或者剪贴的内容 对于经常复制文字的Ubuntu使用者作用还是比较大的 下面附上安装代码 安装: sudo add-apt-repository ppa:shantzu/cl ...

  2. 玛雅游戏[NOIP2011]

    题目描述 Mayan puzzle 是最近流行起来的一个游戏.游戏界面是一个7 行5 列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放在其他方块之上.游戏通关是指在规定 ...

  3. 超超超简单的bfs——POJ-1915

    Knight Moves Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 26102   Accepted: 12305 De ...

  4. DHCP服务的部署和配置

    DHCP介绍: DHCP(动态主机配置协议)是一个局域网网络协议,使用UDP协议工作,主要用途:给局域网络或网络服务供应商自动分配IP地址, DHCP有3个端口,其中UDP67和UDP68为正常的DH ...

  5. Open-Falcon第七步安装报警模块(小米开源互联网企业级监控系统)

    sender调用各个公司提供的mail-provider和sms-provider,按照某个并发度,从redis中读取邮件.短信并发送,alarm生成的报警短信和报警邮件都是直接写入redis即可,s ...

  6. ML: 聚类算法R包-模糊聚类

    1965年美国加州大学柏克莱分校的扎德教授第一次提出了'集合'的概念.经过十多年的发展,模糊集合理论渐渐被应用到各个实际应用方面.为克服非此即彼的分类缺点,出现了以模糊集合论为数学基础的聚类分析.用模 ...

  7. MySQL数据库—日期与时间函数

    一. 日期和时间函数 函数的概念:按指定格式输入参数,返回正确结果的运算单元 1. 返回当前日期:curdate() current_date() current_date()+0可以将当前日期转换为 ...

  8. 程序设计中的数学思维函数总结(代码以C#为例)

    最近以C#为例,学习了程序设计基础,其中涉及到一些数学思维,我们可以巧妙的将这些逻辑问题转换为代码,交给计算机运算. 现将经常会使用到的基础函数做一总结,供大家分享.自己备用. 1.判断一个数是否为奇 ...

  9. Dinic算法详解及实现

    预备知识: 残留网络:设有容量网络G(V,E)及其上的网络流f,G关于f的残留网络即为G(V',E'),其中G'的顶点集V'和G的顶点集V相同,即V'=V,对于G中任何一条弧<u,v>,如 ...

  10. Redis的部署及使用

    Redis Memcached与Redis的对比 Memcached: 优点: 1. 纯set get性能好 2. 开发都会用,易用简单 4. 可用于存放session 缺点: 1. 不支持持久化 2 ...