子集构造法实现NFA的确定化
功能: 采用子集构造算法实现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的确定化的更多相关文章
- 利用子集构造法实现NFA到DFA的转换
概述 NFA非有穷自动机,即当前状态识别某个转换条件后到达的后继状态不唯一,这种自动机不便机械实现,而DFA是确定有限状态的自动机,它的状态转换的条件是确定的,且状态数目往往少于NFA,所以DFA能够 ...
- 【译】N 皇后问题 – 构造法原理与证明 时间复杂度O(1)
[原] E.J.Hoffman; J.C.Loessi; R.C.Moore The Johns Hopkins University Applied Physics Laboratory *[译]* ...
- Uva 120 - Stacks of Flapjacks(构造法)
UVA - 120 Stacks of Flapjacks Time Limit: 3000MS Memory Limit: Unknown 64bit IO Format: %lld &a ...
- [Luogu4724][模板]三维凸包(增量构造法)
1.向量点积同二维,x1y1+x2y2+x3y3.向量叉积是行列式形式,(y1z2-z1y2,z1x2-x1z2,x1y2-y1x2). 2.增量构造法: 1)首先定义,一个平面由三个点唯一确定.一个 ...
- POJ 3295 Tautology (构造法)
Tautology Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 7716 Accepted: 2935 Descrip ...
- 牛客网 牛客小白月赛2 A.数字方阵-反魔方阵,梁邱构造法
天坑未补... 水一波博客,再不写博客就咸成鱼干了,只写题不写题解,过一段时间就忘了自己学过什么了. 最近重点就是把开学以来写的题补出来,没学的就滚去学会啊(= =),填一下坑... 从这篇博客开始, ...
- 紫书 习题 8-24 UVa 10366 (构造法)
又是一道非常复杂的构造法-- #include<cstdio> #include<algorithm> #define REP(i, a, b) for(int i = (a) ...
- 紫书 例题8-17 UVa 1609 (构造法)(详细注释)
这道题用构造法, 就是自己依据题目想出一种可以得到解的方法, 没有什么规律可言, 只能根据题目本身来思考. 这道题的构造法比较复杂, 不知道刘汝佳是怎么想出来的, 我想的话肯定想不到. 具体思路紫书上 ...
- LeetCode42题,单调栈、构造法、two pointers,这道Hard题的解法这么多?
本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是LeetCode专题的第23篇文章. 今天来看一道很有意思的题,它的难度是Hard,并且有许多种解法. 首先我们来看题面,说是我们有若 ...
随机推荐
- 1-PHP基本概念
PHP 概念:服务器脚本语言 静态网站:不支持交互的网站(html) 动态网站:支持数据交互的网站 实现动态网站的技术 实现技术 网站后缀 ASP .asp PHP .php .NET .aspx J ...
- 关于js中两种定时器的设置及清除(转载)
1.JS中的定时器有两种: window.setTimeout([function],[interval]) 设置一个定时器,并且设定了一个等待的时间[interval],当到达时间后,执行对应的方法 ...
- iOS开发之NSOperation & NSOperationQueue
1.简介 (1) NSOperationQueue(操作队列)是由GCD提供的队列模型的Cocoa抽象,是一套Objective-C的API,为了使并发(多线程)编程变得更加简单,但效率比GCD略低. ...
- redis 3.2 报错 Redis protected-mode 配置文件没有真正启动
(error) DENIED Redis is running in protected mode because protected mode is enabled Redis protected- ...
- 百度cdn资源公共库共享及常用开发接口
CDN公共库是指将常用的JS库存放在CDN节点,以方便广大开发者直接调用 网站:http://cdn.code.baidu.com/ 常用资源: jquery: http://libs.baidu.c ...
- 维护Study
##老师发了一个study来让我们纠错维护,整个软件是日程管理系统,分为欢迎界面,登录 注册界面,提醒界面添加日程界面,还有个人中心等.一些主要代码老师让我们把缺失部分去维护.首先我们读一下主要代码# ...
- 反射实现 Data To Model
调用 : public ActionResult Index() { DataTable dt = new DataTable(); dt.Columns.Add("Name"); ...
- POPTEST老李分享修改dns ip的vbs代码
POPTEST老李分享修改dns ip的vbs代码 poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣,请大家咨 ...
- Android实现网络多线程断点续传下载
本示例介绍在Android平台下通过HTTP协议实现断点续传下载. 我们编写的是Andorid的HTTP协议多线程断点下载应用程序.直接使用单线程下载HTTP文件对我们来说是一件非常简单的事.那么,多 ...
- Wpf学习之路……
Wpf学习之路-- Wpf是 .net中一门做winform的技术,和传统的winform的区别在于: 1. 原来的winform就是拖控件,而wpf的控件都死自己拿标记语言(xaml ...