子集构造法实现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,并且有许多种解法. 首先我们来看题面,说是我们有若 ...
随机推荐
- Robots协议
Robots协议 什么是robots? Robots文件:网站和搜索引擎之间的一个协议. 用来防止搜索引擎抓取那些我们不想被搜索引擎看到的隐私内容. Robots文件告诉蜘蛛什么是可以被查看的. ...
- @Autowired 注释对在哪里和如何完成自动连接提供了更多的细微的控制。
1.@Autowired 可以用在多个地方,在 setter 方法上,属性上 或者 带有多个参数的任意方法上. Setter 方法中的 @Autowired. 当 Spring遇到一个在 setter ...
- Python(五)编程小实例
Python(五)编程小实例 抓取网页信息,并生成txt文件内容! Python抓取网页技能--Python抓取网页就是我们常看见的网络爬虫,我们今天所要用到的就是我们Python中自带的模块,用这些 ...
- "浏览器端" 使用 commonjs 模块规范开发网页应用,像开发 node 那样开发网页应用
Containjs 1.0 Containjs 是什么? Containjs 是一个基于 Commonjs 模块管理规范的 浏览器端 的 JavaScript 模块加载器(目前为非标准的,代码会持续迭 ...
- R语言数据分析利器data.table包 —— 数据框结构处理精讲
R语言data.table包是自带包data.frame的升级版,用于数据框格式数据的处理,最大的特点快.包括两个方面,一方面是写的快,代码简洁,只要一行命令就可以完成诸多任务,另一方面是处理 ...
- sass 与 less 的区别与学习
一直使用的都是sass,公司提出新需求要用less,看了一下less的官方文档,感觉记不住.在这我想用与sass的比较学习,加深印象.也希望可以帮助到一些人. 一.安装sass与less sass基于 ...
- apache 配置多个版本的 php
注:这里说的是windows环境下的配置 我们在配置apache+php的时候,是在apache的配置文件httpd.conf里加载php的模块并指定php.ini路径 LoadModule php5 ...
- 实验楼-2-Linux基础快捷键
终端:本质上对应着Linux上的/dev/tty设备 shell:打开终端,shell则自动打开 可以在终端直接输入: echo "hello world" /*shell程序自动 ...
- C++—动态内存管理之深入探究new和delete
C++中程序存储空间除栈空间和静态区外,每个程序还拥有一个内存池,这部分内存被称为自由空间(free store)或堆(heap).程序用堆来存储动态分配的对象,即,那些程序运行时分配的对象.动态对象 ...
- linux 下日常使用便利工具
Nautilus 你工作中有在GUI和命令行之间切来切去吗?当你总是要在命令行中输入你要进入的目录的时候,你有沮丧无奈过吗?如果有的话,那么,你一定要试下这个nautilus插件 —— nautilu ...