1、问题概述

  NFA 和 DFA浅析---要深入了解正则表达式,必须首先理解有穷自动机。

有穷自动机(Finite Automate)是用来模拟实物系统的数学模型,它包括如下五个部分:

    • 有穷状态集States
    • 输入字符集Input symbols
    • 转移函数Transitions
    • 起始状态Start state
    • 接受状态Accepting state(s)(终止状态)

  下图为一台有穷自动机

  

  可以看到,该自动机包含四个状态(有限状态)q0, q1, q2, q3,两个输入字符a, b,转移函数如图所示,起始状态为q0,接受状态为q3。

  有穷自动机,按照转移函数的不同,又可分为确定型有穷自动机(Determinism Finite Automate, DFA),与非确定型有穷自动机(Non-determinism Finite Automate, NFA)
  非确定有穷自动机容许转移函数不确定,换句话说,对任意状态,输入任意一个字符,可以转移到0个,1个或者多个状态。

  下图是一台非确定有穷自动机,可以看到,对状态q0输入字符a,既可以转移到q0,也可以转移到q1,这就是“非确定”的意义所在。

  对某个自动机来说,如果从起始状态,接受一系列输入字符,可以转移到接受状态,即认为这一系列字符可以被自动机接受。
  如果两台自动机能够接受的输入字符串(或者叫做“正则语言”Regular Language)完全相同,则这两台自动机是等价的。可以证明,对于每一个非确定有穷自动机,都存在与之等价的确定型有穷自动机(证明略)。

  正则表达式就是建立在自动机的理论基础上的:用户写完正则表达式之后,正则引擎会按照这个表达式构建相应的自动机(可能是NFA,也可能是DFA,但它们必定是等价的),若输入一串文本之后,自动机抵达了接受状态,则这串文本可以“匹配”用户指定的正则表达式。

  下面是同一个正则表达式 a|ab 对应的NFA和DFA

  

  在Mastering Regular Expression中,Friedl首先分析了NFA和DFA的区别,DFA比较快,但不提供Backtrack(回溯)功能,NFA比较慢,但提供了Backtrack功能

  在分析两种引擎的匹配过程时,Friedl指出,NFA是基于表达式的(Regex-Directed),而DFA是基于文本的(Text-Directed)。

  举例来说,对于正则表达式
to(nite|knight|night),NFA在匹配最开始两个字符(to)之后,剩下的三个组件(component)是 nite,
knight 和
night,于是正则引擎会依次尝试这三个选择分支(每次尝试一个);而DFA在匹配最开始两个字符之后,会将剩下的三个选择拆分作字符,并行尝试,也就是说,匹配
to 之后,先匹配 k 或者 n ,如果 k 不能匹配,则放弃 knigth 所在的分支,再匹配 i ,再匹配 t 或 g
……这样继续下去,直到匹配结束。

  不幸的是,Friedl对匹配过程的分析,是完全错误的——引擎的不同,是指构建的自动机的不同,而不是匹配算法的不同!

  DFA引擎在任意时刻必定处于某个确定的状态,而NFA引擎可能处于一组状态之中的任何一个,所以,NFA引擎必须记录所有的可能路径(trace
multiple possible routes through the
NFA),NFA之所以能够提供Backtrack的功能,原因就在这里。

  传统的NFA匹配算法是带回溯的深度优先搜索(backtracking depth-first search,就是上文所说的Regex-Based过程),而新的PCRE算法提供了效率更高的广度优先搜索,可以同时保持所有可能的NFA状态(请参考http://www.cl.cam.ac.uk/Teaching/current/RLFA/,尤其是Lecture Notes的section 2.2)。

  Friedl的错误就在这里,他混淆了应用PCRE算法的NFA与DFA的匹配过程。需
要指出的是,即使应用PCRE算法,NFA的速度仍然低于DFA,这是由NFA需要同时保存多种可能的性质决定的。从理论上说,如果我们不需要应用
Backtrack,完全可以从NFA构造出等价的DFA,再进行匹配,这样能大大提高速度——代价是,DFA需要更多的空间。

原文地址:http://www.cnblogs.com/u2usoft/archive/2006/06/06/419003.html

endl;

参考网址:

  http://blog.csdn.net/yukuninfoaxiom/article/details/6057736

编译系统中的 NFA/DFA算法理解的更多相关文章

  1. NFA/DFA算法

    1.问题概述 随着计算机语言的结构越来越复杂,为了开发优秀的编译器,人们已经渐渐感到将词 法分析独立出来做研究的重要性.不过词法分析器的作用却不限于此.回想一下我们的老师刚刚开始向我们讲述程序设计的时 ...

  2. 编译系统中的LR与LL理解

    编译原理:LL(1),LR(0),SLR(1),LALR(1),LR(1)对比 LL(1)定义:一个文法G是LL(1)的,当且仅当对于G的每一个非终结符A的任何两个不同产生式 A→α|β,下面的条件成 ...

  3. 敏感词汇过滤DFA算法

    using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Tex ...

  4. Java 利用DFA算法 屏蔽敏感词

    原文:http://www.open-open.com/code/view/1435214601278 import java.io.BufferedReader; import java.io.Fi ...

  5. java实现敏感词过滤(DFA算法)

    小Alan在最近的开发中遇到了敏感词过滤,便去网上查阅了很多敏感词过滤的资料,在这里也和大家分享一下自己的理解. 敏感词过滤应该是不用给大家过多的解释吧?讲白了就是你在项目中输入某些字(比如输入xxo ...

  6. 利用 DFA 算法实现文字过滤

    一.DEA 算法简介 在实现文字过滤的算法中,DFA是唯一比较好的实现算法. DFA 全称为:Deterministic Finite Automaton,即确定有穷自动机.其特征为:有一个有限状态集 ...

  7. 基于DFA算法、RegExp对象和vee-validate实现前端敏感词过滤

    面临敏感词过滤的问题,最简单的方案就是对要检测的文本,遍历所有敏感词,逐个检测输入的文本是否包含指定的敏感词. 很明显上面这种实现方法的检测时间会随着敏感词库数量的增加而线性增加.系统会因此面临性能和 ...

  8. DFA算法实现敏感词过滤

    DFA算法:即确定有穷自动机,简单点说就是,它是是通过event和当前的state得到下一个state,即event+state=nextstate.理解为系统中有多个节点,通过传递进入的event, ...

  9. 关于KMP算法理解(快速字符串匹配)

    参考:http://www.ruanyifeng.com/blog/2013/05/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm.html 2016-08- ...

随机推荐

  1. JS valueOf与字符串

    js在处理字符串和数值加运算的时候会转换数值为字符串 然后执行字符串连接 在覆盖String.prototype.valueOf之前,new String(111)这样的字符串与数值加法也是字符串连接 ...

  2. ANDROID调用webservice带soapheader验证

    最近的一个项目中调用webservice接口,需要验证soapheader,现将解决方法记录如下:(网上资料出处太多,就不做引用,原作者如看到,如有必要添加请通知) 1.先看接口 POST /webs ...

  3. Git学习(一)——Git介绍与安装

    一.Git诞生 Linus在1991年创建了Linux,从此,Linux系统不断发展,成为最大的服务器系统软件. 2005年,Linus用C编写了一个分布式版本控制工具--Git. 二.集中式vs分布 ...

  4. (转载)持续集成(第二版)[来自:Martin Fowler]

    转载自:iTech的博客 持续集成(第二版) 作者:Martin Fowler 译者:雷镇 持续集成 是一种软件开发实践.在持续集成中,团队成员频繁集成他们的工作成果,一般每人每天至少集成一次,也可以 ...

  5. 《锋利的jQuery》(第2版)读书笔记4

    第9章 jQuery Mobile jQuery Mobile是用来填补jQuery在移动设备应用上的缺憾的一个新项目. 它基于jQuery框架并使用HTML5和CSS3这些新的技术,除了能提供很多基 ...

  6. 转载:Bootstrap之表格checkbox复选框全选

    转:http://blog.csdn.net/shangmingchao[商明超的博客] 效果图: HTML中无需添加额外的一列来表示复选框,而是由JS完成,所以正常的表格布局就行了: 版权声明:如需 ...

  7. SQL Server 查询所有外键子父表关系

    SELECT table_name,fk_name,reference_table_name,fk_list_number,fk_detailFROM (SELECT object_name(f.ob ...

  8. JS验证字符长度

    function getStrLength(str) { var cArr = str.match(/[^\x00-\xff]/ig); return str.length + (cArr == nu ...

  9. Nginx配置upstream实现负载均衡

    如果Nginx没有仅仅只能代理一台服务器的话,那它也不可能像今天这么火,Nginx可以配置代理多台服务器,当一台服务器宕机之后,仍能保持系统可用.具体配置过程如下: 1. 在http节点下,添加ups ...

  10. 重启php-fpm的方法

    ps -ef|grep "php-fpm: master process"|grep -v grep|awk '{print $2}'|xargs kill -USR2   优点: ...