正规式转换到非确定有穷自动机转换的一般算法

mac2026-10-01  4

要求

用C++ 实现;input.txt描述正规式,需要编程加以解析,该文件规定的格式为:第一行写处正规式的符号集,规定符号集为0-9共10个数字符,第二行写正规式,如: 0123456789(0|1)*0.10* (注:*表示闭包运算,.表示连接该符号可省略) output.txt为描述非确定有穷自动机的文件,有程序生成,生成时需按如下格式: 第一行写出状态集,用大写字母A-Z表示,如:ABCD第二行描述自动机的符号集为0-9共10个数字符,如:0123456789第三行写初态集,如:A第四行写终态集,如:CD第五行写出转移函数,如(A,0,B)表示A状态的出边0到达B状态。上例正规式可表为(A,0,A)(A,1,A)(A,0,B)(B,1,C)(C,0,D)(D,0,D)。

思路

使用Thompson构造法,输入为字母表Σ上的正规式,输出为相等的NFA。具体方法为:

首先将构成r的各个元素分解,对于每一个元素,按下述规则1和规则2生成NFA。(注意:如果r中记号a出现了多次,那么对于a的每次出现都需要生成一个单独的NFA。)之后依照正规表达式r的文法规则,将生成的NFA按照下述规则3组合在一起。

规则1 对于空记号ε,生成下面的NFA。 规则2 对于Σ的字母表中的元素a,生成下面的NFA。 规则3 令正规表达式R和S的NFA分别为N(R)和N(S)。对于R|S,按照以下的方式生成NFA N(R|S)。 对于RS,按照以下的方式生成NFA N(RS)。 对于R*,按照以下的方式生成NFA N(R*)。

流程图

总体流程图 在正规式中加入省略的连接符 将式子转为后缀表达式 将后缀表达式转换成NFA

数据结构

struct edge { char weight; char next; }; string option,expression, suffix, infix, postion; map<char, int> precedence; map<char, vector<edge>> nfa; vector<string> tfunction; // 具体解释如下: // edge:NFA图中的边; // option:输入的符号集; // expression:输入的正规式; // infix:增加连接符的正规式; // suffix:转换成的后缀表达式; // postion:状态集; // precedence:规定运算符优先级; // nfa:生成的NFA(使用map生成了一个char与edge向量的映射,char代表NFA中的顶点,也就是生成了一个顶点与从顶点出发边的集合的映射); // tfunction:转移函数。

代码详见 Github上,欢迎star!

最新回复(0)