实验C----NFA转换为DFA
Time Limit: 1000ms, Special Time Limit:2500ms, Memory Limit:65536KB
Total submit users: 74, Accepted users: 58
Problem 13120 : Special judge
Problem description
  有限状态自动机(FSM "finite state machine" 或者FSA "finite state automaton" )是为研究有限内存的计算过程和某些语言类而抽象出的一种计算模型。有限状态自动机拥有有限数量的状态,每个状态可以迁移到零个或多个状态,输入字串决定执行哪个状态的迁移。有限状态自动机可以表示为一个有向图。有限状态自动机是自动机理论的研究对象。 定义:有限状态自动机(FA—finite automaton)是一个五元组:
  ? M=(Q, Σ, δ, q0, F)
  · 其中,
  ? Q——状态的非空有穷集合。?q∈Q,q称为M的一个状态。
  ? Σ——输入字母表。
  ? δ——状态转移函数,有时又叫作状态转换函数或者移动函数,δ:Q×Σ→Q,δ(q,a)=p。
  ? q0——M的开始状态,也可叫作初始状态或启动状态。q0∈Q。
  ? F——M的终止状态集合。F被Q包含。任给q∈F,q称为M的终止状态。
  非确定有限状态自动机(NFA)与确定有限状态自动机(DFA)的唯一区别是它们的转移函数不同。确定有限状态自动机对每一个可能的输入只有一个状态的转移。非确定有限状态自动机对每一个可能的输入可以有多个状态转移,接受到输入时从这多个状态转移中非确定地选择一个。下图是一个非确定性有限状态自动机(NFA)的例子:

图一 一个NFA的图文表示
  转移函数δ定义自下列状态转移表:

δ 0 1
q0 {q0} {q0q1q2}
q1 {q2} {q3}
q2 {} {q3}
q3 {q3} {q3}

  表示状态集合的子集合,采用二进制(特征)串的方式,一个子集中包含该状态,对应的特征串就为1,否则为0,比如上面状态集合的子集{q0q1q2},其特征串就是0111,而子集{q0},其特征串就是0001。将对应的特征串转换为十进制的数字,得到转移函数δ:

δ 0 1
q0 1 7
q1 4 8
q2 0 8
q3 8 8

  你的任务,是要将一个给定的NFA转换为一个完全等价的DFA(有限状态自动机等价的意思是识别相同的语言)。这里我们约定自动机识别的字符集为{0,1},初始状态集合为Q0,状态集为{q0,q1,…,qn-1}。

Input

  输入第一行只有一个正整数t,表示有t个测试数据(意味着t个NFA)t≤10;
  对于每组测试数据(每个NFA),首先是3个正整数n,Q0,f,分别表示状态数、起始状态集合和接受状态集合的特征串对应的整数。n≤10;Q0,f < 2n;
  接下来两行是NFA的转移函数矩阵,第一行是每个状态在输入为0的状态转移情况,用特征串对应的整数表示;第二行是每个状态在输入为1的状态转移情况。

Output

  对于每个NFA,输出四行表示与之等价的DFA。输出格式如下:
  第一行3个空格隔开的整数a b c,分别表示DFA的状态数,接受状态数,起始状态的编号(从0开始对状态编号)。要求 a < 65536。
  b,c ≤ a 第二行b个空格分隔的整数,表示每个接收状态的编号,每个编号的值一定在[0,a)之间。
  第三行、第四行每行a个空格分隔的整数,表示DFA的转移函数矩阵,第三行第i个值ui表示状态转移函数的一项δ(qi,0)→ui,第四行第i个值vi表示状态转移函数的一项δ(qi,1)→vi,,每个ui,vi的值一定在[0,a)之间。

Sample Input
  1.   1
  2.   4 1 8
  3.   1 4 0 8
  4.   7 8 8 8
Sample Output
  1.   16 8 1
  2.   8 9 10 11 12 13 14 15
  3.   0 1 4 5 0 1 4 5 8 9 12 13 8 9 12 13
  4.   0 7 8 15 8 15 8 15 8 15 8 15 8 15 8 15
Judge Tips
  样例中的NFA如图一所示
  与某个NFA等价的DFA不一定是唯一的,比如和图一等价的DFA可以是样例的解答,也可以是如下的DFA

  1.   4 1 0
  2.   3
  3.   0 2 0 3
  4.   1 3 3 3

  本题会使用special judge,只要是符合条件的解答都可以接受(Accept)。

1、算法设计思路

  状态集合的子集合,采用二进制(特征)串的方式,一个子集中包含该状态,对应的特征串就为1,否则为0,比如上面状态集合的子集{q0q1q2},其特征串就是0111,而子集{q0},其特征串就是0001。将对应的特征串转换为十进制的数字,得到转移函数δ。

2、实验总结

  在转化的过程中经NFA中状态矩阵中的每一个状态的集合映射到DFA中的一个状态。即NFA中的状态子集为一个DFA中的状态;只要NFA状态子集中有一个为接受态,相应的映射的DFA中的状态就为接受态

3、AC代码

  1. #include<cstdio>
  2. #include<cstdlib>
  3. #include<iostream>
  4. #include<cstring>
  5. #include<cmath>
  6. #define M 99999
  7. using namespace std;
  8. int ans[M];
  9. int one[M];
  10. int zero[M];
  11. int lft[M];
  12. int rgt[M];
  13. int change[M];
  14. bool vis[M];
  15. bool ac[M];
  16.  
  17. int cnt, n, q, f;
  18. int index(int p)
  19. {
  20. int x = 1;
  21. if(p == 1)
  22. return 0;
  23. int i = 0;
  24. while(++i)
  25. {
  26. x <<= 1;
  27. if(p == x)
  28. return i;
  29. }
  30. return 0;
  31. }
  32. int mege(int a, int b)
  33. {
  34. while(b)
  35. {
  36. int x = b&(-b);
  37. if(!(a&x))
  38. a ^= x;
  39. b ^= x;
  40. }
  41. return a;
  42. }
  43. void dfs(int p)
  44. {
  45. ans[cnt] = p;
  46. int lsum = 0, rsum = 0;
  47. while(p)
  48. {
  49. int x = p&(-p);
  50. int y = index(x);
  51. lsum = mege(lsum, zero[y]);
  52. rsum = mege(rsum, one[y]);
  53. p ^= x;
  54. }
  55. lft[cnt] = lsum;
  56. rgt[cnt] = rsum;
  57. cnt++;
  58. if(!vis[lsum])
  59. vis[lsum] = 1, dfs(lsum);
  60. if(!vis[rsum])
  61. vis[rsum] = 1, dfs(rsum);
  62. }
  63.  
  64. int main()
  65. {
  66. int t;
  67. scanf("%d", &t);
  68. while(t--)
  69. {
  70. scanf("%d%d%d", &n, &q, &f);
  71. for(int i = 0; i < n; i++)
  72. scanf("%d", &zero[i]);
  73. for(int i = 0; i < n; i++)
  74. scanf("%d", &one[i]);
  75. cnt = 0;
  76. memset(vis, 0, sizeof(vis));
  77. memset(ac, 0, sizeof(ac));
  78. vis[q] = 1;
  79. dfs(q);
  80. int sum = 0;
  81. for(int i = 0; i < cnt; i++)
  82. if(ans[i]&f)
  83. ac[i] = 1, sum++;
  84. for(int i = 0; i < cnt; i++)
  85. change[ans[i]] = i;
  86. printf("%d %d %d\n", cnt, sum, 0);
  87. for(int i = 0, j = 0; i < cnt; i++)
  88. {
  89. if(ac[i])
  90. {
  91. if(j)
  92. printf(" ");
  93. printf("%d", i);
  94. j++;
  95. }
  96. }
  97. printf("\n");
  98. for(int i = 0; i < cnt; i++) {
  99. if(i)
  100. printf(" ");
  101. printf("%d", change[lft[i]]);
  102. }
  103. printf("\n");
  104. for(int i = 0; i < cnt; i++){
  105. if(i)
  106. printf(" ");
  107. printf("%d", change[rgt[i]]);
  108. }
  109. printf("\n");
  110.  
  111. }
  112. return 0;
  113. }

湖大OJ-实验C----NFA转换为DFA的更多相关文章

  1. 湖大OJ-实验E----可判定的DFA的空问题

    实验E----可判定的DFA的空问题 Time Limit: 1000ms, Special Time Limit:2500ms, Memory Limit:32768KB Total submit ...

  2. NFA转换为等价的DFA

    在编译系统中,词法分析阶段是整个编译系统的基础.对于单词的识别,有限自动机FA是一种十分有效的工具.有限自动机由其映射f是否为单值而分为确定的有限自动机DFA和非确定的有限自动机NFA.在非确定的有限 ...

  3. 利用子集构造法实现NFA到DFA的转换

    概述 NFA非有穷自动机,即当前状态识别某个转换条件后到达的后继状态不唯一,这种自动机不便机械实现,而DFA是确定有限状态的自动机,它的状态转换的条件是确定的,且状态数目往往少于NFA,所以DFA能够 ...

  4. NFA转DFA - json数字识别

    json的主页上,提供了number类型的符号识别过程,如下: 图片引用:http://www.json.org/json-zh.html 实际上这张图片表示的是一个状态机,只是状态没有标出来.因为这 ...

  5. nfa转dfa,正式完成

    为了加速转换的处理,我压缩了符号表.具体算法参考任何一本与编译或者自动机相关的书籍. 这里的核心问题是处理传递性闭包,transitive closure,这个我目前采取的是最简单的warshall算 ...

  6. 计算理论:NFA转DFA的两种方法

    本文将以两种方法实现NFA转DFA,并利用C语言实现. 方法二已利用HNU OJ系统验证,方法一迷之WA,但思路应该是对的,自试方案,测试均通过. (主要是思路,AC均浮云,大概又有什么奇怪的Case ...

  7. 求子串-KPM模式匹配-NFA/DFA

    求子串 数据结构中对串的5种最小操作子集:串赋值,串比较,求串长,串连接,求子串,其他操作均可在该子集上实现 数据结构中串的模式匹配 KPM模式匹配算法 基本的模式匹配算法 //求字串subStrin ...

  8. 各大Oj平台介绍 刷题平台

    https://leetcode.com/ http://www.cnblogs.com/lzmfywz/archive/2012/02/07/2342010.html 1.题库与网站资源题库-在线提 ...

  9. 各大Oj平台介绍

    1.题库与网站资源题库-在线提交系统(Online Judge)简介   下面是几个比较大的在线提交系统(OnlineJudge)里面有大量历年的竞赛题目,注册一个ID,然后用自己熟悉的语言(一般有P ...

随机推荐

  1. 优化特性(Attribute)性能

    通过这篇文章,不仅可以了解到Attribute的工作原理,还可以了解到GetcustomeAttribute是的内部执行流程.最后,你会看到,使用缓存机制可以极大的优化反射Attribute的性能. ...

  2. iOS 评论APP撰写评论

    ---- iOS 应用评分 UIAlertAction *alertAction1 = [UIAlertAction actionWithTitle:@"方式1 跳转到app商店" ...

  3. OpenSceneGraph学习笔记

    VirtualPlanetBuilder编译方法 转自:http://www.boyunjian.com/do/article/snapshot.do?uid=7327932418831703800 ...

  4. Oracle函数解析

    一:大小写控制函数 lower()函数:(此函数将全部的大写字母都可以变为小写字母) upper()函数:(将输入的字符串变为大写字母) initcap()函数:(将每个字符串的首字母大写)  二:字 ...

  5. js中常用的Tab切换

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  6. bootstrap学习笔记之一

    一.概要 bootstrap是最受欢迎的HTML.css和js框架,用于开发响应式布局,移动设备优先的WEB项目. 二.CSS部分 1.bootstrap已经设定了基本的全局样式,如font-fami ...

  7. PHP脱mysql脚本

    <?php $SQL_Server="xxxxxx:3306"; $SQL_User="xxxx"; $SQL_Name="xxxx" ...

  8. mysql导数据库用到的语句

    将字段格式为2013-08-09 13:22:55转换为时间戳 UPDATE `AttendClass` SET `regdate` = unix_timestamp(regDate2) WHERE ...

  9. php中使用while遍历二维数组的方法

    <?php $contact=array( 'gao'=>array('ID'=>1,'name'=>'高某','company'=>'A公司','addr'=>' ...

  10. Eclipse序列号生成代码

    import java.io.*; public class MyEclipseGen { private static final String LL = "Decompiling thi ...