自己实现一个 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 设计 ...
随机推荐
- Java泛型详解,通俗易懂只需5分钟
转载出处:http://www.weixueyuan.net/view/6321.html 我们知道,使用变量之前要定义,定义一个变量时必须要指明它的数据类型,什么样的数据类型赋给什么样的值. 假如我 ...
- Jmeter 常用函数(17)- 详解 __substring
如果你想查看更多 Jmeter 常用函数可以在这篇文章找找哦 https://www.cnblogs.com/poloyy/p/13291704.htm 作用 从字符串中获取指定范围的子串 语法格式 ...
- 进阶6:连接查询 一、sql92标准
#进阶6:连接查询/*含义:又称多表查询,当查询的字段来自于多个表时,就会用到连接查询 笛卡尔乘积现象:表1 有m行,表2有n行,结果=m*n行 发生原因:没有有效的连接条件如何避免:添加有效的连接条 ...
- JavaFX桌面应用-SpringBoot + JavaFX
SpringBoot对于Java程序员来说可以是一个福音,它让程序员在开发的时候,大大简化了各种spring的xml配置. 那么在JavaFX项目使用SpringBoot会是怎么样的体验呢? 这次使用 ...
- Synergy--跨平台的键鼠共享工具
目前的状态,Windows并没有彻底放弃使用,现在一个电脑桌上摆放了一台Mac pro 一台Windows,两个笔记本都是15寸的,如果想要方便的使用外设鼠标键盘,整个桌子会异常的臃肿,鼠标键盘太占地 ...
- 兼容低版本IE浏览器的一些心得体会(持续更新)
前言: 近期工作中,突然被要求改别人的代码,其中有一项就是兼容IE低版本浏览器,所以优雅降级吧. 我相信兼容低版本IE是许多前端开发的噩梦,尤其是改别人写的代码,更是痛不欲生. 本文将介绍一些本人兼容 ...
- 02 . Go开发一个日志收集平台之Context及etcd简单使用
Context简单使用 context设置,获取value值 应用于全局通用参数传递 package main import ( "context" "fmt" ...
- python yaml文件数据按原有的数据顺序dump
yml文件的更新后工具类: import os import yaml class YamlUtils(): def __init__(self,folder_name='config'): self ...
- 焦大:做SEO应该研究的用户需求的方向
http://www.wocaoseo.com/thread-60-1-1.html 最近收到打击很大,收获也颇多,这一切都莫过于用户需求的问题.我曾经给我弟说过,我对检索排名特征识别.提取和计算自认 ...
- 5分钟快速学会xpath定位
今天我们先来和大家说一下appium,首先教大家如何定位xpath,五分钟即可学会:例:现在我想定位下面这个登录按钮: xpath该怎么写呢? 先不管三七二十几,先写//,然后找你要定位元素最近的可以 ...