正则表达式

文章原文https://white-night.club/index.php/2023/04/23/study12/

在之前我们提到过正则文法RG的定义:左部为语法变量,右部为语法变量或语法变量与字符串的连接。例子如下(大写字母表示语法变量):

A→B | A→ωB | A→B

而除了用正则文法描述单词外,还可以用正则表达式(regular expression)来描述单词。

正则表达式的定义

与正则文法等价

给定一个字母表Σ,则它的正则表达式有:

  • Ø 表示空集
  • ε 表示空字符串集合 { ε }
  • 对应任意字母表中的一个字符a,所得的正则表达式为它本身,即 a。
  • 如果r和s都是Σ上的正则表达式,那么有:
    • r | s也是Σ上的正则表达式,“|”表示或。
    • r · s也是Σ上的正则表达式,“·”表示连接,一般可以省略不写。
    • r*也是Σ上的正则表达式,“*”表示克林闭包。

而正则表达式代表的语言或集合则被称为正则集(regular set)。

直接给个例子,比如字母表Σ={a,b},那么它的正则表达式以及正则表达式表示的集合有:

  • 正则表达式:a|b
    • 正则集:{a,b}
  • 正则表达式:aa|bb
    • 正则集:{aa,bb}
  • 正则表达式:(a)(a|b) 等价于 aa|ab
    • 正则集:{aa,ab}
  • 正则表达式:a*
    • 正则集:{ε,a,aa,aaa,…}
  • 正则表达式:(a|b)*
    • 正则集:{ε,a,b,aa,bb,ab,abbbb,…}(由a和b构成的字符串的集合)

正则表达式的代数定律

常用于其等价变换

综上我们可以看到,正则表达式还满足一些代数定律:

  • 或符号 |
    • 满足交换律 r|s=s|r
    • 满足结合律 r|(s|t)=(r|s)|t
  • 连接符号 ·
    • 满足结合律 (rs)t=r(st)
    • 对于或符号满足分配律 r(s|t)=rs|rt
  • 克林闭包符号 *
    • 满足 r*=(r|ε)*
    • 满足幂等关系 r**=r*

其中,正则表达式还满足以下规则:

  • 克林闭包与正闭包之间的转换
    • r*=r+|ε (克林闭包比正闭包多一个空字符串ε的体现)
    • r+=r*r=rr* (表示的集合中的字符串,至少由一个r组成)
  • 符号 ?,表示“0或一个”
    • r?=r|ε。其表示的集合为{ε,r}
  • 字符类,使用方括号[ ]简写正则表达式
    • [a-z]表示正则表达式 a|b|c|d|e|…|z
    • [0-9]表示正则表达式0|1|2|…|9
    • [A-Za-z][A-Za-z0-9]*表示正则表达式 (A|…|Z|a|…|z)(A|…|Z|a|…|z|0|…|9)*。该正则表达式可以用来描述标识符的集合(其中标识符不能以数字开头)。

正则表达式↔正则集

相关例题

我们整两个课后习题巩固下相关知识。

先来道从正则表达式→正则集的:

给定正则表达式 ((ε|0)1*)* ,求其正则集

先看最外层,克林闭包大致表示:字符的无限种组合。那么最外层的克林闭包符号不如向括号内移,得到

((ε|0)*1*)* (其中1**=1*)

发现(ε|0)*可以等价为0*。继续得到

(0*1*)*

到这就很明显了,该正则表达式表示的集合:由0和1构成的字符串,其中包括空字符串ε。其正则集为

{ε,0,1,001,011,…} 或 {x|x是0和1构成的字符串,包括ε}

形式语言与自动机

额外拓展

接上面,再来个正则集→正则表达式的例题:

给定正则集 {x|x∈{0,1}+ & x中不含有形如10110的子串},求其正则表达式。

很明显,你直接想是很难想出来该怎么写的,得画状态转换图。但这块的知识在《形式语言与自动机》中,所以建议各位先看网课自学并掌握以下内容:

  • 状态消除法–将状态转换图化为正则表达式。
  • 怎么画状态转换图?状态转换图表达的含义是什么?

言归正传,在本题中,你应该能得出这个状态转换图

q0-q4的状态转换图

  • 图的入度(或入边):表示“向其指向的图输入某个值”。
  • 图的出度(或出边):表示“向其指向的图输出某个值”。
  • 边上的字符:表示输入或输出的值。
  • 图自己指向自己:表示克林闭包。如图中的q0→q0,表示q0向q0输出(0*).

接下来是利用状态消除法将该图化为正则表达式,状态消除法的规则如下:

  • 向图中添加起始点和终点,并设置读入/读到空字符串ε。不然最后消去所有节点后图就是空白的了。
  • 找到某个要消去的节点(假设为q4)
  • 忽略其自己指向自己的边。然后计算它的出度n和入度m(q4入度为1;出度为1)
  • 去掉该节点以及和它相连的所有边。并在图中的某个节点上补充m*n条边。

对于该题,我们已经有了它的状态转换图,接下来就是将它转换为正则表达式。

写者注

附:作图的时候忘记加双层圆了,实际上q0-q4这五个节点都应该加上双层圆。表示“自动机可以在该节点终止”。具体的建议各位自行了解。

将其转换为正则表达式,我们需要对图中的每个“终止状态”,通过状态消除法,添加起始点和终点求解正则表达式。

以该图为例,先以q0为终止状态,添加对应的终点。(可能缺点细节,但不影响)

以q0为终点

然后消去q4。分析q4的入度和出度:

  • 入度:q3-q4
  • 出度:q4-q1

可见我们需要补上m*n,即一条边。所补的边应该是q3-q1。

从q3到q1,需要经过1→1*→1。所以q1应该读入11*1。得到图为

去掉q4

接着我们去掉q3,它的出入度情况为

  • 入度:q2-q3
  • 出度:q3-q2 q3-q1

说明我们需要补两条边,分别是:q2-q2,q2-q1。

q2读入10,转入状态q0;q2读入1-11*1-1*,即111*11*,转入状态q1,所得状态图为:

去掉q3

接下来去掉q2,和上面过程一样,得到图:

去掉q2

接下来就是去掉q1了,得到图:

去掉q1

现在只剩q0。很明显,把q0去掉,所得到的结果就是q0为终点的正则表达式。结果如下

(0+1(1+0(10)*(111*11*))*(0(10)*0))*

当然,根据你去掉节点顺序的不同,最后得到的结果也不同。但这些结果之间是等价的、可以相互转换的.

然后再对q1-q4这几个节点做相同的操作,最后得到的正则表达式相加便是结果。(但这过程太长;而且说实话,想了下我写的q0确实等价于答案给的q0,但我忙活半天,这纸质过程真写不出来。所以这里直接放结果了)。

标签:编译原理

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值