子集构造法实现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,并且有许多种解法. 首先我们来看题面,说是我们有若 ...
随机推荐
- 【WCF】错误处理(二):错误码―—FaultCode
先来说说SOAP消息中错误消息的包装结构,一条SOAP错误消息的大致形式如下: <s:Fault> <faultcode xmlns:a="me-cust-error&qu ...
- struts2(二) 表单参数自动封装和参数类型自动转换
前篇文章对struts2的一个入门,重点是对struts2的架构图有一个大概的了解即可,之后的几篇文章,就是细化struts2,将struts2中的各种功能进行梳理,其实学完之后,对struts2的使 ...
- (18)IO流之字节缓冲路
缓冲流 BufferedInputStream 缓冲输入流 前面的练习告诉我们使用缓冲数组读取的效率更高,为了方便的大家的操作,sun 位大家提供了一个缓冲输入字节流对象,让我们可以更高效率的读取文件 ...
- 微信小程序-开发入门
微信小程序已经火了一段时间了,之前一直也在关注,就这半年的发展来看,相对原生APP大部分公司还是不愿意将主营业务放到微信平台上,以免受制于腾讯,不过就小程序的应用场景(用完即走和二维码分发等)还是很值 ...
- Tcl与Design Compiler (四)——DC启动环境的设置
本文属于原创手打(有参考文献),如果有错,欢迎留言更正:此外,转载请标明出处 http://www.cnblogs.com/IClearner/ ,作者:IC_learner 主要内容有: ·启动环 ...
- Jmeter-添加检查点
JMeter里面的检查点通过添加断言来完成. 检查用户名和密码参数化的文件user.dat有没有正确调用,添加断言,可以在结果树中查看结果. 1.添加响应断言,右键点击HTTP请求"ts1后 ...
- Jquery EasyUI远程校验,Jquery EasyUI多个自定义校验,EasyUI自定义校验
>>>>>>>>>>>>>>>>>>>>>>>>> ...
- 深入浅出数据结构C语言版(6)——游标数组及其实现
在前两次博文中,我们由表讲到数组,然后又由数组的缺陷提出了指针式链表(即http://www.cnblogs.com/mm93/p/6576765.html中讲解的带有next指针的链表).但是指针式 ...
- 老李推荐:第6章3节《MonkeyRunner源码剖析》Monkey原理分析-事件源-事件源概览-命令翻译类
老李推荐:第6章3节<MonkeyRunner源码剖析>Monkey原理分析-事件源-事件源概览-命令翻译类 每个来自网络的字串命令都需要进行解析执行,只是有些是在解析的过程中直接执行 ...
- Android Weekly Notes Issue #251
Android Weekly Issue #251 April 2nd, 2017 Android Weekly Issue #251. 本期内容: Android O新增的API: View的too ...