[编译原理随记]正则表达式转为NFA状态图(Thompsion构造法)

上级文章

[编译原理随记]正则表达式记号和状态图:[编译原理随记]正则表达式记号和状态图_状态转换图正则表达式_qq_28033719的博客-CSDN博客

[编译原理随记]NFA转DFA子集构造算法:[编译原理随记]NFA转DFA子集构造算法_(a|b)*abb(a|b)*转换成dfa_qq_28033719的博客-CSDN博客


准备知识

语法制导:

解析(parse)输入的字符串时,在特定位置执行指定的动作。

语法制导算法:

其实就本文内容,解析字符串是什么状态(像>=通常弄个状态图,如果是关键字弄个表暂存比较适合)来说,这个算法相当于对字符串每一个字符进行下一个状态判断,就是 switch(string.charAt(i))这样逐个处理。

NFA状态数 = 正则表达式的 (符号 + 操作符数) * 2:

举例,比如说正则里面常有的运算符 *,| ,连接符,这些作为操作符,在下面的正则输入状态解析为:

1、输入 ε 和 a(符号),NFA状态图为:

状态数都是 2 = 1(符号数为1) * 2

2、输入 s|t ,NFA状态图为:

状态数是 6 = 3(符号数2 + 操作数1) * 2

3、s*,NFA状态图为:

状态数是 4 = 2(符号数1 + 操作符数1) * 2

所以每多一个符号数或者操作符数,对原图新增的状态数最多2,很多情况都是原状态 多了一个 空串 状态

出边入边,出度入度:

前后者概念有相似,出边入边本文指状态 A 转到下一个状态的边(A\overset{a}{\rightarrow})为出边,进入状态A的边(\overset{a}{\rightarrow}A)为入边.

而后者指的是数量,出度就是专指有向图的出边A\overset{a}{\rightarrow} 的出边数量),而入度是入边数(\overset{a}{\rightarrow}A 的入边数量),图的度的概念与树的度的概念相区别。

NFA三点性质:

1、NFA状态数 = 正则表达式的 (符号 + 操作符数) * 2

2、开始状态无入边,终结状态无出边

3、每个状态有一个[A-Za-z0-9]出边,或者至多两个 ε


Thompsion构造法

例题:将正则表达式  (a|b)*abb 变为 NFA

先将复合正则变为最基本的子表达式,然后进行语法制导(一步一步来)。

1、先处理优先度高的组合 (a | b),首先开始无入边,终结无出边,然后状态有一个字符出边,或者至多两个 ε

2、处理 (a|b)*,一样,根据 NFA 三性质得出,6 -> 1 状态代表循环输入,1 不能作为开始(有入边)6不能作为终结(有出边):

3、再把 abb 拼上去就行了:

3展示的就是 从正则 (a|b)*abb 转的 状态图。


模拟NFA

用双栈模拟:

因为 ε-closure(move(T , a)), T代表一个状态集合 比如T={1,2}

然后S = ε-closure(move(T , a)), S代表T移动a之后的集合 比如 S={3,4},T S都是多个元素,不是一个确定状态(DFA就是一个)。

所以使用两个(存储方面可以理解为数组,只是crud操作不同),存放 S、T 两种状态的转换(因为状态不确定,所以下一个状态是一个集合)

具体算法是:

S := ε-closure(0);
a := nextchar; // 理解为超前标记
while a != eof do begin
    S := ε-closure(move(S , a));
    a := nextchar;
end

// F 为终结集合
if S ∩ F != ∅ then
    return "yes";
return "no";

当然,将 NFA -> DFA也可以不过,这两者都需要衡量空间复杂度和时间复杂度。


DFA 和 NFA 时间空间衡量

NFA 空间是 <= 正则表达式的 (符号 + 操作符数) * 2

DFA 空间是 <= 2 ^ n (n为(a|b)字符数量,因为这个或运算使用状态数最多,所以推断任意数量 符号 + 操作符数)

NFA 时间复杂度 = 正则表达式的 (符号 + 操作符数) * X(输入的字符串长度,因为每个字符串都匹配)

DFA 时间复杂度 = X(因为每个字符都有一个确定状态,不用遍历)


下级文章:

[编译原理随记]正则表达式构建DFA(r(#)followpos(i)构造):[编译原理随记]正则表达式构建DFA(r(#)followpos(i)构造)_正则表达式构造dfa_qq_28033719的博客-CSDN博客

  • 5
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值