子集构造法实现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,并且有许多种解法. 首先我们来看题面,说是我们有若 ...
随机推荐
- Redis的发布订阅及.NET客户端实现
序言 发布订阅在设计模式中也可以说是观察者模式,针对这个模式是处理对象间一对多的依赖关系的,当一个对象发生变化,其它依赖他的对象都要得到通知并更新. 然而它也有自己的缺点,就是当主题发生一系列的变化时 ...
- Pydev for eclipse 安装及配置
1.安装JDK,eclipse 2.打开eclipse->help->install new software,点Add,名称输入:Pydev,更新链接为:http://pydev.org ...
- 用Visual Studio Code Debug世界上最好的语言
前言 这阵子因缘巧合接手了一个辣鸡项目,是用世界上最好的拍黄片写的,项目基本是另一个小伙伴在撸码,我就兼职打杂和发布做点运维的工作. 然后昨天项目上了测试版之后,一用起来Error满天飞了.让小伙伴查 ...
- 10分钟精通SharePoint-搜索
大势所趋随着企业内容和文档数量的骤增,快速定位到所需材料和内容已经迫不及待,这也是所有企业所面临的共同的挑战,应这个大的趋势,"搜索"闪亮登上了企业协作(SharePoint)舞台 ...
- 解决error104 connection reset by peer;socket error问题
这个问题原因有两个: 1.因为你访问网站太多次,所以被网站管理员给禁止访问了. 解决方法: 1.延长time.sleep时间 2.设置代理 2.根本没有这个网站.(打开链接检查一下!!!)
- iOS开发RunLoop
最近处于离职状态,时间也多了起来,但是学习还是不能放松,今天总结一下RunLoop,RunLoop属于iOS系统层的东西,还是比较重要的. 一.什么是RunLoop 字面意思看是跑圈,也可以看作运行循 ...
- php线程安全与非线程安全版的区别
Thread Safe(线程安全)和 None Thread Safe(非线程安全) 背景: Linux/Unix系统采用多进程的工作方式,而Windows系统采用多线程的工作方式. CGI模式是建立 ...
- 计算机程序的思维逻辑 (75) - 并发容器 - 基于SkipList的Map和Set
上节我们介绍了ConcurrentHashMap,ConcurrentHashMap不能排序,容器类中可以排序的Map和Set是TreeMap和TreeSet,但它们不是线程安全的.Java并发包中与 ...
- ORA-01994: GRANT failed: password file missing or disabled
1.错误现象 SQL> grant sysdba to test;grant sysdba to test*ERROR at line 1:ORA-01994: GRANT failed: pa ...
- JavaScript对象原型写法区别
体现对象原型分步式写法 //原型分步式写法 //构造函数 function Person(){} //对象原型 Person.prototype.name = 'Avensatr'; Pers ...