自己实现一个 DFA 串模式识别器(二)
正规表达式的实现原理
上文讨论了串的模式的表达,即正规表达式。那么这一小节将讨论我们实现一个正规表达式的方法和原理。因为我们知道,一个正规表达式对应着一个串模式,而一个串模式又对应着一些列符合该模式描述的规则的串。那么,我们是否可以通过实现出正规表达式,从而实现对一个给定串的判别呢?答案是肯定的。
状态转换图
首先介绍,状态转换图。
状态转换图是一个有向图,由节点和边组成。每个节点代表一个状态,状态之间用箭头连接,称为边。边上的字符表示从该边的出发节点读取一个该边上的字符后,可以抵达改变指向的状态节点。如下图:
状态转换图中具有一个状态标记为 start 状态,被称为初始状态。识别一个字符串时,我们就从这个状态开始。下图展示了能够识别 大于号 或者 大于等于号 的状态转换图:
其开始状态是状态 0,在状态 0 读入下一个字符,如果该字符是 > ,那么则转向状态 1,否则失败。在状态 1 时,读入下一个字符,如果是 + ,则转向状态 2,否则标有 other 的边表明转向状态 3.在状态 2 上有双圈,表示它是接受状态。当进入这个状态时,状态转换图识别了记号 >= 。
通常会有多个状态转换图,每个状态转换图对应者一个类别(如记号)。如果沿着一个状态转换图书别串时失败,那么就需要将前向指针回退到该状态图开始状态时该指针所指向的输入串的位置。并启动下一个状态转换图,试图匹配下一个模式。显然,我们可以通过不断的组合状态转换图来实现更加复杂的串模式匹配。可以说,状态转换图为串模式识别提供了一种有效方法。
所以状态转换图实现了正规表达式和图结构的转换。上面的状态转换图对应着正规表达式:>(\(\epsilon\)|=) 。而图结构十分容易使用计算机实现。
有穷自动机
有穷自动机是更一般化的状态转换图。它可以是确定的即 DFA,也可以是不确定的即 NFA。其中“不确定”的含义是:对于某个输入符号,在同一个状态上存在不止一种转换。我们可以通过构造有穷自动机把正规表达式编译成识别器。二者都可以识别且仅能识别正规集,即能够识别正规表达式所表示的字符串集合。但是二者有着时空上的权衡,DFA 导出的识别器比NFA导出的识别器要快得多,但DFA可能比与之等价的NFA大得多。(注:NFA,DFA 的数学模型定义这里从略)
NFA
由于从正规式转换成不确定的有穷自动机(NFA)更方便,所以先讨论 NFA。
下图是一个 NFA:
它所对应的正规表达式为:(a|b)*abb 。注意,NFA 是用带标记的有向图表示,称为转换图,节点是状态,有标记的边是转换关系。NFA 这种转换图与之前的状态转换图很类似,但是区别是:同一个字符可以标记始于同一个状态的两个或多个转换,边上可以有输入字符符号,也可以有特殊符号 \(\epsilon\) 。
从正规表达式构造 NFA
这里采用一个简单的算法来实现这种构造。首先构造自动机使其能够识别任何 \(\epsilon\) 的字母表中的任何符号,然后由此构造自动机来识别包含一个交、一个连接或者一个克林闭包运算符的正规表达式。如对于正规表达式:a|b 可以先分别构造字符 a 和 b 的自动机,然后在从二者的 NFA 构造出 a|b 的 NFA。该算法被称为 Thompson 构造法。
自己实现一个 DFA 串模式识别器(二)的更多相关文章
- 自己实现一个 DFA 串模式识别器
自己实现一个 DFA 串模式识别器 前言 这是我编译原理课程的实验.希望读完这篇文章的人即便不知道 NFA,DFA 和正规表达式是什么,也能够对它们有一个简单的理解,并能自己去实现一个能够识别特定模式 ...
- WCF学习之旅—TCP双工模式(二十一)
WCF学习之旅—请求与答复模式和单向模式(十九) WCF学习之旅—HTTP双工模式(二十) 五.TCP双工模式 上一篇文章中我们学习了HTTP的双工模式,我们今天就学习一下TCP的双工模式. 在一个基 ...
- WCF学习之旅—HTTP双工模式(二十)
WCF学习之旅—请求与答复模式和单向模式(十九) 四.HTTP双工模式 双工模式建立在上文所实现的两种模式的基础之上,实现客户端与服务端相互调用:前面介绍的两种方法只是在客户端调用服务端的方法,然后服 ...
- MFC如何生成一个可串行化的类
一.MFC允许对象在程序运行的整个过程中持久化的串行化机制 (1)串行化是指向持久化存储媒介(如一个磁盘文件)读或写对象的过程. (2)串行化用于在程序运行过程时或之后修复结构化数据(如C++类或结构 ...
- OOAD-设计模式(二)之GRASP模式与GOF设计模式概述
一.GRASP模式(通用责任分配软件模式)概述 1.1.理解责任 1)什么是责任 责任是类间的一种合约或义务,也可以理解成一个业务功能,包括行为.数据.对象的创建等 知道责任——表示知道什么 行为责任 ...
- VC++ MFC如何生成一个可串行化的类
一.MFC允许对象在程序运行的整个过程中持久化的串行化机制(1)串行化是指向持久化存储媒介(如一个磁盘文件)读或写对象的过程.(2)串行化用于在程序运行过程时或之后修复结构化数据(如C++类或结构)的 ...
- 设计模式之代理模式之二(Proxy)
from://http://www.cnblogs.com/xwdreamer/archive/2012/05/23/2515306.html 设计模式之代理模式之二(Proxy) 0.前言 在前 ...
- python设计模式之常用创建模式总结(二)
前言 设计模式的创建模式终极目标是如何使用最少量最少需要修改的代码,传递最少的参数,消耗系统最少的资源创建可用的类的实例对象. 系列文章 python设计模式之单例模式(一) python设计模式之常 ...
- Java 设计模式之工厂模式(二)
原文地址:Java 设计模式之工厂模式(二) 博客地址:http://www.extlight.com 一.背景 本篇内容是 Java 设计模式创建型模式的第二篇.上一篇主题为 <Java 设计 ...
随机推荐
- cannot find package "cloud.google.com/go/compute/metadata"
问题: cannot find package "cloud.google.com/go/compute/metadata" 解决: mkdir $GOPATH/src/cloud ...
- 浅谈Docker(二)
Docker使用cgroup实现CPU,内存和磁盘IO等系统资源的限制. CPU Docker现在有2个与CPU资源相关的参数,-c可以指定CPU的占比,--cpuset可以绑定CPU.例如,指定容器 ...
- 独立集(bubble) 题解
问题描述 有一天,一个名叫顺旺基的程序员从石头里诞生了.又有一天,他学会了冒泡排序和独立集.在一个图里,独立集就是一个点集,满足任意两个点之间没有边.于是他就想把这两个东西结合在一起.众所周知,独立集 ...
- 计算机网络-网络层(1)IPv4和IPv6
IPv4数据报格式: 版本号 这4比特规定了数据报的IP 协议版本.通过查看版本号,路由器能够确定如何解释IP数据报的剩余部分. 首部长度 以4字节为单位,没有选项的首部长度为5*4=20字节 服务类 ...
- 手写Promise简易版
话不多说,直接上代码 通过ES5的模块化封装,向外暴露一个属性 (function(window){ const PENDING = 'pending'; const RESOLVED = 'fulf ...
- ms-data(转载)
转载:https://www.cnblogs.com/zll-52011/p/10960905.html 1.从美国矿物数据库下载矿物CIF(有晶格) 2.晶胞CIF导入MS 3.选择display ...
- Docker 镜像构建之 Dockerfile
在 Docker 中创建镜像最常用的方式,就是使用 Dockerfile.Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明.官方文档:https://d ...
- Combine 框架,从0到1 —— 2.通过 ConnectablePublisher 控制何时发布
本文首发于 Ficow Shen's Blog,原文地址: Combine 框架,从0到1 -- 2.通过 ConnectablePublisher 控制何时发布. 内容概览 前言 使用 ma ...
- MySQL锁这块石头似乎没有我想的那么重
前言 前言为本人写这篇文章的牢骚,建议跳过不看. 之前好几次都想好好的学习MySQL中的锁,但是找了几篇文章,看了一些锁的类型有那么多种,一时间也没看懂是什么意思,于是跟自己说先放松下自己,便从书 ...
- composer安装依赖包时,php内存分配不足
Fatal error: Allowed memory size of 1610612736 bytes exhausted (tried to allocate 4096 bytes) in pha ...