功能: 采用子集构造算法实现NFA的确定化

输入:读取NFA的文件(文件名test.txt),  文件格式:

第一列表示状态名,第二列和第三列分别表示输入字符a和b到达的状态

输出:确定化后的DFA(文件名为output.txt),格式如下:

第一列表示输入状态名,第二列表示重新命名的状态名,第三列和第四列分别表示输入字符a和b所到达的状态

代码:

 #include <stdio.h>
 #include <string.h>
 /* 子集构造算法实现NFA的确定化
 * 输入文件:test.txt的内容
 * 状态名   输字符a到达的状态 字符b到达的状态
 * 0        {0,1}            {0,2}
 * 1        {f}                {NULL}
 * 2        {NULL}            {f}
 * f        {f}                {f}

 * 输出文件:out.test的内容(输入状态名,字符a到达的状态,字符b到达的状态)

 * {0,}ABC
 * {0,2,}CBD
 * {0,2,f,}DED
 * {0,1,f,}EED
 * {0,1,}BEC
 *
 *@author: finch
 *@time  : 2017-4-29
 */

 #define num 10             //状态集合大小
 #define stack_Size 10      //栈的大小

 ][];      //Dstates

 /*
  NFA信息表
 */
 struct nfa_info
 {
     char  c;
     char a[num];
     char b[num];

 }nfa[num];

 /*
   DFA信息表
 */
 struct dfa
 {
     char c[num];
     char a[num];
     char b[num];
 }dfa[num];

 /*
   栈:用于实现未标记的状态的存储
      可以用Dstates替代
 */
 struct  stack_info
 {
     char data[stack_Size][stack_Size];
     int top;
 };

 typedef stack_info stack;

 /*
   栈的 初始化

 */
 void initStack(stack *S)
 {
     S->top = -;                // -1空栈
 }

 /*
   栈是否为空
   是: 返回 1
   否: 返回 0
 */
 int IsEmpty(stack *S)
 {

     )
     {
         ;
     }
     else {
         ;
     }
 }

 /*
   将字符串 str入栈
 */
 int push(stack *S, char str[])
 {
     S->top++;
     if (S->top >= stack_Size)
     {
         printf("the stack is full\n");
         ;
     }
     strcpy(S->data[S->top], str);
     printf("\n%d-%s\n", S->top, S->data[S->top]);

     ;
 }

 /*
 栈顶元素出栈
 赋值给str
 */
 int  pop(stack *S, char str[])        //出栈
 {

     )
     {
         printf("\nthe stack is empty\n");
         ;
     }

     strcpy(str, S->data[S->top]);
     ; i < num; i++)
     {
         S->data[S->top][i] = '\0';
     }
     S->top--;
     ;
 }

 /*
 U是否在Dstates中
 在:返回1
 否:返回0
 */
 int isBiaoji(char U[])
 {
     ;
     ; Dstates[i][] != '\0';i++)
     {
          == strcmp(U, Dstates[i]))
             state = ;
     }
     return state;
 }

 /*
 是否属于NFA
 */
 int isElem(char ch)
 {
     ') || (ch >= 'A'&&ch <= 'Z'))
         ;
     else
         ;
 }

 /*
 从文件中读取数据并存到NFA中
 */
 void input()                        //输入
 {
     FILE *fp_in;
     fp_in = fopen("test.txt", "r");
     if (fp_in == NULL)
     {
         printf("Error\n");
     }
     else {
         char c;
         ;                   //行数
         ;
         ;       

         c = fgetc(fp_in);
         while (c != EOF)            //文件结束标志
         {

             if (c == '\n')
             {
                 i++;
                 printf("\n");
                 j = ;
             }
             else if (c == '{')               //遇见左括号,新的字符串
             {
                 j++;                        //状态+1
                 index = ;                  //新的集合
             }
             )
             {
                 )                 //state
                 {
                     nfa[i].c = c;
                     printf("C:%c\t", nfa[i].c);
                 }
                 )           //经过a边到达的点
                 {
                     nfa[i].a[index] = c;
                     printf("A:%c\t", nfa[i].a[index]);
                     index++;
                 }
                 else                      //经过b边到达的点
                 {
                     nfa[i].b[index] = c;
                     printf("B:%c\t", nfa[i].b[index]);
                     index++;
                 }
             }
             else
             {
                 ;
             }
             c = fgetc(fp_in);
         }
         fclose(fp_in);
     }

 }

 /*
 将字符串str2中独有
 的字符放到str1中
 @time:2017-4-23
 */
 void  strcatIgnorReat(char str1[], char str2[])
 {
     ];
     ; i < ;i++)
     {
         x[i] = '\0';
     }
     )                        //str1为空 ,直接连接
     {
         strcat(str1, str2);
     }
     else
     {
         strcpy(x, str2);
         ; str1[i] != '\0';i++)
         {
             ; x[j] != '\0';j++)
             {
                 if (str1[i] == x[j])
                 {
                     x[j] = '#';                  //相同的用#替代
                 }
             }
         }

         ;i < strlen(x);i++)
         {
             if (x[i] != '#')
             {
                 int index = strlen(str1);
                 str1[index] = x[i];
             }
         }
     }

 }

 /*
 状态c经过输入符号a上的转换可以到达
 的NFA状态集合nfa_set
 @time: 2017/4/23
 @finch
 */
 int move(char c, int a, char nfa_set[])
 {

     ;
     while (nfa[i].c != c && nfa[i].c != '\0')        //状态c在NFA中的位置
     {
         i++;
     }
     if (nfa[i].c == c)
     {
         )                                 //a边
         {
              != strcmp("NULL", nfa[i].a))
             {

                 strcatIgnorReat(nfa_set, nfa[i].a);  //经过a可以到达的NFA状态集合
             }
         }
         else {
              != strcmp("NULL", nfa[i].b))      //b边
                 strcatIgnorReat(nfa_set, nfa[i].b);     //经过b可以到达的NFA状态集合
         }

         ;
     }
     else {
         ;
     }
 }

 /*
 NFA确定化函数
 从NFA状态Set开始可以转换
 @time  2017/4/22
 @finch
 */
 void turn(char Set[], stack *S)                  //NFA确定化函数
 {
     ;                             //标记数量
     ;                             //DFA下标
     push(S, Set);                               //Set入栈
     ];                              //每个集合经过的所有点的集合
     strcpy(Dstates[bj_num], Set);
     bj_num++;
      == IsEmpty(S))                     //栈不为空
     {
         char U[num];                            //缓存
         pop(S, U);                              //元素出栈
         index++;

         strcpy(dfa[index].c, U);                //DFA
         ;a != ;a++)              //分别对a,b边遍历
         {
             ; i < ;i++)
             {
                 buff[i] = '\0';                 //清空
             }

             ; U[i] != '\0'&&i < num; i++) //遍历str集合
             {
                 move(U[i], a, buff);
             }
             )
             {
                 strcpy(dfa[index].a, buff);                   //结合str在a边上的集合
             }
             else
             {
                 strcpy(dfa[index].b, buff);                   //结合str在b边上的集合
             }
              == isBiaoji(buff))&&(strlen(buff)!=))     //新的非空集合未标记入栈并标记
             {
                 push(S, buff);
                 strcpy(Dstates[bj_num], buff);
                 bj_num++;
             }
         }

     }
 }

 /*
 打印
 @time 2017/4/23
 */
 void print()
 {
     printf("\n\n");
     ; dfa[i].c[] != '\0';i++)
     {
         printf("<%s>\t\t<%s>\t\t<%s>\n", dfa[i].c, dfa[i].a, dfa[i].b);
     }
 }

 /*
 返回set在Dstates中的位置
 返回 -1: 不存在
 */
 int getIndex(char set[])
 {
     ;
     ; Dstates[i][] != '\0';i++)
     {
          == strcmp(set, Dstates[i]))
             state = i;
     }
     return state;
 }
 /*
 输出
 @time 2017/4/23
 @finch
 */
 void output()
 {
     FILE *fp_out = NULL;
     if ((fp_out = fopen("output.txt", "w+")) == NULL)
     {
         printf("Error:can't open the file !");
     }
     else {

         ; dfa[i].c[] != '\0';i++)                  //重命名
         {
             fprintf(fp_out, "{", dfa[i].c);
             ; dfa[i].c[j] != '\0';j++)
             {
                 fprintf(fp_out, "%c,", dfa[i].c[j]);
             }
             fprintf(fp_out, "}", dfa[i].c);

             fprintf(fp_out, "%c", 'A' + getIndex(dfa[i].c));

              == getIndex(dfa[i].a))                        //符号a上的集合为空
             {
                 fprintf(fp_out, "\t{%s}", "NULL");
             }
             else {
                 fprintf(fp_out, "\t%c", 'A' + getIndex(dfa[i].a));
             }
              == getIndex(dfa[i].b))                        //符号b上的集合为空
             {
                 fprintf(fp_out, "\t{%s}", "NULL");
             }
             else {
                 fprintf(fp_out, "\t%c", 'A' + getIndex(dfa[i].b));
             }
             fprintf(fp_out, "\n");
         }
     }
     fclose(fp_out);
 }
 int main()
 {
     stack S;
     initStack(&S);
     input();
     turn(", &S);
     print();
     output();
     ;
 }

子集构造法实现NFA的确定化的更多相关文章

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

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

  2. 【译】N 皇后问题 – 构造法原理与证明 时间复杂度O(1)

    [原] E.J.Hoffman; J.C.Loessi; R.C.Moore The Johns Hopkins University Applied Physics Laboratory *[译]* ...

  3. Uva 120 - Stacks of Flapjacks(构造法)

    UVA - 120  Stacks of Flapjacks Time Limit: 3000MS   Memory Limit: Unknown   64bit IO Format: %lld &a ...

  4. [Luogu4724][模板]三维凸包(增量构造法)

    1.向量点积同二维,x1y1+x2y2+x3y3.向量叉积是行列式形式,(y1z2-z1y2,z1x2-x1z2,x1y2-y1x2). 2.增量构造法: 1)首先定义,一个平面由三个点唯一确定.一个 ...

  5. POJ 3295 Tautology (构造法)

    Tautology Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7716   Accepted: 2935 Descrip ...

  6. 牛客网 牛客小白月赛2 A.数字方阵-反魔方阵,梁邱构造法

    天坑未补... 水一波博客,再不写博客就咸成鱼干了,只写题不写题解,过一段时间就忘了自己学过什么了. 最近重点就是把开学以来写的题补出来,没学的就滚去学会啊(= =),填一下坑... 从这篇博客开始, ...

  7. 紫书 习题 8-24 UVa 10366 (构造法)

    又是一道非常复杂的构造法-- #include<cstdio> #include<algorithm> #define REP(i, a, b) for(int i = (a) ...

  8. 紫书 例题8-17 UVa 1609 (构造法)(详细注释)

    这道题用构造法, 就是自己依据题目想出一种可以得到解的方法, 没有什么规律可言, 只能根据题目本身来思考. 这道题的构造法比较复杂, 不知道刘汝佳是怎么想出来的, 我想的话肯定想不到. 具体思路紫书上 ...

  9. LeetCode42题,单调栈、构造法、two pointers,这道Hard题的解法这么多?

    本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是LeetCode专题的第23篇文章. 今天来看一道很有意思的题,它的难度是Hard,并且有许多种解法. 首先我们来看题面,说是我们有若 ...

随机推荐

  1. HTML超文本标记语言-基础标签整理

    第一章 <META>标签: <meta http-equiv="Content-Type" Content="text/html;charset=gb2 ...

  2. JavaScript 基础阶段测试题

    JavaScript 基础阶段测试题,试试你能得多少分? 一.选择题1.分析下段代码输出结果是( )    var arr = [2,3,4,5,6];    var sum =0;    for(v ...

  3. 基于Spring Cloud和Netflix OSS构建微服务,Part 2

    在上一篇文章中,我们已使用Spring Cloud和Netflix OSS中的核心组件,如Eureka.Ribbon和Zuul,部分实现了操作模型(operations model),允许单独部署的微 ...

  4. (23)IO之打印流 PrintStream & Printwriter

    PrintStream PrintStream可以接受文件和其他字节输出流,所以打印流是对普通字节输出流的增强,其中定义了很多的重载的print()和println(),方便输出各种类型的数据. Pr ...

  5. python3的urllib2报错问题解决方法

    python urlib2 兼容问题 在python3中,将urllib和urllib2合并了,所以在使用urllib2的地方改成urllib.request即可.示例如下 import urllib ...

  6. Windbg调试中遇到的问题

    1.找不到符号文件 抓取完Dump后,打开WinDbg,Ctrl+D找到刚才抓取的Dump文件,报如下异常: *** ERROR: Symbol file could not be found. De ...

  7. VC++中经常出现的内存泄露和指针问题

    要养成良好的编程习惯,每次用new开辟的新空间马上先写好释放语句delete.指针在程序中往往有很多细节问题,比如1.指针作为返回值,某个分支中进行赋值返回,另一个分支却没有值.2.指针作为函数参数传 ...

  8. 01.Nodejs入门之Helloworld

    说明:本文章可供有一定js基础的朋友参考nodejs入门,本文未讲解nodejs的安装,如有需要的同学可以加QQ3382260752找我,进行交流学习. 1.新建文件夹helloworld demo, ...

  9. 手机自动化测试:搭建appium手机自动化测试开发环境

    手机自动化测试:搭建appium手机自动化测试开发环境   poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣,请大 ...

  10. 性能调优案例分享:jvm crash的原因 1

    性能调优案例分享:jvm crash的原因   poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣,请大家咨询qq: ...