从0到1打造为有限状态自动机(finite-state automation)

本文是一篇教你如何从零开始构建一个能执行正则表达式的有限状态自动机(Finite-state automation)的教程。通过理论与实践结合,详细介绍了正则表达式下的串联匹配、并连匹配、重复匹配、特殊符号和子表达式等,并提供了代码实现,包括建图和匹配过程。文章最后提到了NFA和DFA引擎的性能对比以及未来可能的优化方向。
摘要由CSDN通过智能技术生成

今天是五一假期第一天,这里先给大家拜个晚 咳咳!!祝大家五一快乐,我这里给大家奉上一篇硬核教程。首先声明,这篇文章不是教你如何写正则表达式,而是教你写一个能执行正则表达式的执行引擎。 网上教你写正则表达式的文章、教程很多,但教你写引擎的并不多。很多人认为我就是用用而已,没必要理解那么深,但知道原理是在修炼内功,正则表达式底层原理并不单单是用在这,而是出现在计算机领域的各个角落。理解原理可以让你以后写字符串匹配时正则表达式能够信手拈来,理解原理也是触类旁通的基础。废话不多说,直接开始正式内容。

 

本文是我个人做的动手实践性项目,所以未完整支持所有语法,而且因为是用NFA实现的所以性能比生产级的执行引擎差好多。目前源码已开放至www.jintianxuesha.com,后续会继续更新,欢迎Star、Fork 提PR。

目前支持的正则语义如下:

  • 基本语法: . ? * + () |
  • 字符集合: []
  • 特殊类型符号: \d \D \s \S \w \W

前置知识

声明:本文不是入门级的文章,所以如果你想看懂后文的内容,需要具备以下的基本知识。

  1. 基本的编程知识,虽然这里我是用java写的,但并不要求懂java,懂其他语法也行,基本流程都是类似,就是语法细节不同。
  2. 了解正则表达式,知道简单的正则表达式如何写。
  3. 基本的数据结构知识,知道有向图的概念,知道什么是递归和回溯。

有限状态机

有限状态机(Finite-state machine),也被称为有限状态自动机(finite-state automation),是表示有限个状态以及在这些状态之间的转移和动作等行为的数学计算模型(From ) 。 听起来晦涩难懂,我用大白话描述一遍,状态机其实就是用图把状态和状态之间的关系描述出来,状态机中的一个状态可以在某些给定条件下变成另外一种状态。举个很简单的例子你就懂了。

比如我今年18岁,我现在就是处于18岁的状态,如果时间过了一年,我就变成19岁的状态了,再过一年就20了。当然我20岁时时光倒流2年我又可以回到18岁的状态。这里我们就可以把我的年龄状态和时间流逝之间的关系用一个自动机表示出来,如下。
在这里插入图片描述
每个圈代表一个节点表示一种状态,每条有向边表示一个状态到另一个状态的转移条件。上图中状态是我的年龄,边表示时间正向或者逆向流逝。

有了状态机之后,我们就可以用状态机来描述特定的模式,比如上图就是年龄随时间增长的模式。如果有人说我今年18岁,1年后就20岁了。照着上面的状态机我们来算下,1年后你才19岁,你这不是瞎说吗! 没错,状态机可以来判定某些内容是否符合你状态机描述的模式了。哟,一不小心就快扯到正则表达式上了。
我们这里再引入两种特殊的状态:起始态接受态(终止态),见名知意,不用我过多介绍了吧,起始态和终止态的符号如下。
在这里插入图片描述
我们拿状态机来做个简单的字符串匹配。比如我们有个字符串“zsx”,要判断其他字符串是否和"zxs"是一致的,我们可以为"zxs"先建立一个自动机,如下。
在这里插入图片描述
对于任意一个其他的字符串,我们从起始态0开始,如果下一个字符能匹配到0后边的边上就往后走,匹配不上就停止,一直重复,如果走到终止态3说明这个字符串和”zxs“一样。任意字符串都可以转化成上述的状态机,其实到这里你就知道如何实现一个只支持字符串匹配的正则表达式引擎了,如果想支持更多的正则语义,我们要做的更多。

状态机下的正则表达式

我们再来引入一条特殊的边,学名叫$\epsilon$闭包(emm!看到这些符号我就回想起上学时被数学支配的恐惧),其实就是一条不需要任何条件就能转移状态的边。
在这里插入图片描述
没错,就只这条红边本边了,它在正则表达式状态机中起着非常重要的连接作用,可以不依赖其他条件直接跳转状态,也就是说在上图中你可以直接从1到2。
有了 $\epsilon$闭包的加持,我们就可以开始学如何画正则表达式文法对应的状态机了。

串联匹配

首先来看下纯字符匹配的自动机,其实上面已经给过一个"zxs"的例子了,这里再贴一下&#x

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值