自己实现一个 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 设计 ...
随机推荐
- 提升布局能力!理解 CSS 的多种背景及使用场景和技巧
CSS background是最常用的CSS属性之一.然而,并不是所有开发人员都知道使用多种背景.这段时间都在关注使用多种背景场景.在本文中,会详细介绍background-image`属性,并结合图 ...
- 操作系统-I/O(2)设备的分配
作业执行前对设备提出申请时,指定某台具体的物理设备会让设备分配变得简单,但如果所指定设备出现故障,即便计算机系统中有同类设备也不能运行 设备独立性:用户通常不指定物理设备,而是指定逻辑设备,使得用户作 ...
- 如何在Linux上使用xargs命令
大家好,我是良许. 在使用 Linux 时,你是否遇到过需要将一些命令串在一起,但是其中一个命令不接受管道输入的情况呢?在这种情况下,我们就可以使用 xargs 命令.xargs 可以将一个命令的输出 ...
- Fiddler或Charles文件转换为Jmeter可执行脚本
解决脚本录制问题,可以将Fiddler或Charles转换成对应的Jmeter脚本,实现部分内容的参数化配置,通过修改部分参数或参数化可以对http协议的接口进行自动化测试或简单的压力测试 GitHu ...
- WebApis中DOM操作的基本案例
1.1. 排他操作 1.1.1 排他思想 如果有同一组元素,我们想要某一个元素实现某种样式, 需要用到循环的排他思想算法: 所有元素全部清除样式(干掉其他人) 给当前元素设置样式 (留下我自己) 注意 ...
- SwiftUI - Grid View 的实现方法,逐步剖析助你实现
简介 在当前正式 SwiftUI 版本而言,很多控件都是缺少的.比如在 UIKit 框架里有 UICollectionView 组件,可以很方便地做 Gird 格子类型的视图.但是在 SwiftUI ...
- JDBC | 第七章: JDBC数据库连接池使用
概述 数据库连接池是负责分配.管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个.那么其中的运行机制又是怎样的呢?今天主要介绍一下数据库连接池原理和常用的连接池. ...
- 基于Log4Net记录日志到SQLServer(自定义字段)
本文记录通过log4net将日志信息记录到SQLServer数据库中. 1.新建控制台应用程序 Log4NetDemo: 2.通过NuGet安装Log4Net (项目版本2.0.8): 3.项目根目录 ...
- Springboot-Mybatis-进阶
目录 数据库关系 ResultMap association collection 动态sql if where set choose foreach 缓存 一级缓存 二级缓存 开启二级缓存 配置 异 ...
- uni-app 修改富文本信息中的图片样式
var richtext= res.data.data.richtext; const regex = new RegExp('<img', 'gi'); richtext= richtext. ...