`
sunqing0316
  • 浏览: 41125 次
  • 性别: Icon_minigender_2
文章分类
社区版块
存档分类
最新评论

软考进行时——DFA和NFA

 
阅读更多

1.历史:

引用

正则表达式萌芽于1940年代的神经生理学研究,由著名数学家Stephen Kleene第一个正式描述。具体地说,Kleene归纳了前述的神经生理学研究,在一篇题为《正则集代数》的论文中定义了“正则集”,并在其上定义了一个代数系统,并且引入了一种记号系统来描述正则集,这种记号系统被他称为“正则表达式”。在理论数学的圈子里被研究了几十年之后,1968年,后来发明了UNIX系统的Ken Thompson第一个把正则表达式用于计算机领域,开发了qed和grep两个实用文本处理工具,取得了巨大成功。在此后十几年里,一大批一流计算机科学家和黑客对正则表达式进行了密集的研究和实践。在1980年代早期,UNIX运动的两个中心贝尔实验室和加州大学伯克利分校分别围绕grep工具对正则表达式引擎进行了研究和实现。与之同时,编译器“龙书”的作者Alfred Aho开发了Egrep工具,大大扩展和增强了正则表达式的功能。此后,他又与《C程序设计语言》的作者Brian Kernighan等三人一起发明了流行的awk文本编辑语言。到了1986年,正则表达式迎来了一次飞跃。先是C语言顶级黑客Henry Spencer以源代码形式发布了一个用C语言写成的正则表达式程序库(当时还不叫open source),从而把正则表达式的奥妙带入寻常百姓家,然后是技术怪杰Larry Wall横空出世,发布了Perl语言的第一个版本。自那以后,Perl一直是正则表达式的旗手,可以说,今天正则表达式的标准和地位是由Perl塑造的。Perl 5.x发布以后,正则表达式进入了稳定成熟期,其强大能力已经征服了几乎所有主流语言平台,成为每个专业开发者都必须掌握的基本工具。



2.DFA和NFA

引用
理解DFA和NFA
正则表达式引擎分成两类,一类称为DFA(确定性有穷自动机),另一类称为NFA(非确定性有穷自动机)。两类引擎要顺利工作,都必须有一个正则式和一个文本串,一个捏在手里,一个吃下去。DFA捏着文本串去比较正则式,看到一个子正则式,就把可能的匹配串全标注出来,然后再看正则式的下一个部分,根据新的匹配结果更新标注。而NFA是捏着正则式去比文本,吃掉一个字符,就把它跟正则式比较,匹配就记下来:“某年某月某日在某处匹配上了!”,然后接着往下干。一旦不匹配,就把刚吃的这个字符吐出来,一个个的吐,直到回到上一次匹配的地方。
DFA与NFA机制上的不同带来5个影响:
1. DFA对于文本串里的每一个字符只需扫描一次,比较快,但特性较少;NFA要翻来覆去吃字符、吐字符,速度慢,但是特性丰富,所以反而应用广泛,当今主要的正则表达式引擎,如Perl、Ruby、Python的re模块、Java和.NET的regex库,都是NFA的。
2. 只有NFA才支持lazy和backreference等特性;
3. NFA急于邀功请赏,所以最左子正则式优先匹配成功,因此偶尔会错过最佳匹配结果;DFA则是“最长的左子正则式优先匹配成功”。
4. NFA缺省采用greedy量词(见item 4);
5. NFA可能会陷入递归调用的陷阱而表现得性能极差。

我这里举一个例子来说明第3个影响。

例如用正则式/perl|perlman/来匹配文本 ‘perlman book’。如果是NFA,则以正则式为导向,手里捏着正则式,眼睛看着文本,一个字符一个字符的吃,吃完 ‘perl’ 以后,跟第一个子正则式/perl/已经匹配上了,于是记录在案,往下再看,吃进一个 ‘m’,这下糟了,跟子式/perl/不匹配了,于是把m吐出来,向上汇报说成功匹配 ‘perl’,不再关心其他,也不尝试后面那个子正则式/perlman/,自然也就看不到那个更好的答案了。

如果是DFA,它是以文本为导向,手里捏着文本,眼睛看着正则式,一口一口的吃。吃到/p/,就在手里的 ‘p’ 上打一个钩,记上一笔,说这个字符已经匹配上了,然后往下吃。当看到 /perl/ 之后,DFA不会停,会尝试再吃一口。这时候,第一个子正则式已经山穷水尽了,没得吃了,于是就甩掉它,去吃第二个子正则式的/m/。这一吃好了,因为又匹配上了,于是接着往下吃。直到把正则式吃完,心满意足往上报告说成功匹配了 ‘perlman’。

由此可知,要让NFA正确工作,应该使用 /perlman|perl/ 模式。

通过以上例子,可以理解为什么NFA是最左子式匹配,而DFA是最长左子式匹配。实际上,如果仔细分析,关于NFA和DFA的不同之处,都可以找出道理。而明白这些道理,对于有效应用正则表达式是非常有意义的。

写道
正则表达式的形式定义故意非常精简,避免定义多余的量词 ? 和 +,它们可以被表达为: a+ = aa* 和 a? = (a|ε)。有时增加补算子 ~ ;~R 指示在 Σ* 上的不在 R 中的所有字符串的集合。补算子是多余的,因为它使用其他算子来表达(尽管计算这种表示的过程是复杂的,而结果可能指数性的增大)。
这种意义上的正则表达式可以表达正则语言,精确的是可被有限状态自动机接受的语言类。但是在简洁性上有重要区别。某类正则语言只能用大小指数增长的自动机来描述,而要求的正则表达式的长度只线性的增长。正则表达式对应于乔姆斯基层级的类型-3文法。在另一方面,在正则表达式和不导致这种大小上的爆炸的非确定有限状态自动机(NFA)之间有简单的映射;为此 NFA 经常被用作正则表达式的替代表示。
我们还要在这种形式化中研究表达力。如下面例子所展示的,不同的正则表达式可以表达同样的语言: 这种形式化中存在着冗余。
有可能对两个给定正则表达式写一个算法来判定它们所描述的语言是否本质上相等,简约每个表达式到极小确定有限自动机,确定它们是否同构(等价)。
这种冗余可以消减到什么程度? 我们可以找到仍有完全表达力的正则表达式的有趣的子集吗? Kleene 星号和并集明显是需要的,但是我们或许可以限制它们的使用。这提出了一个令人惊奇的困难问题。因为正则表达式如此简单,没有办法在语法上把它重写成某种规范形式。过去公理化的缺乏导致了星号高度问题。最近 Dexter Kozen 用克莱尼代数公理化了正则表达式。
很多现实世界的“正则表达式”引擎实现了不能用正则表达式代数表达的特征。

目前正则引擎支持的语言种类:

引擎类型 程序
DFA awk(大多数版本)、egrep(大多数版本)、flex、lex、MySQL、Procmail
传统型 NFA GNU Emacs、Java、grep(大多数版本)、less、more、.NET语言、PCRE library、Perl、PHP(所有三套正则库)、Python、Ruby、set(大多数版本)、vi
POSIX NFA mawk、Mortice Lern System's utilities、GUN Emacs(明确指定时使用)
DFA/NFA混合 GNU awk、 GNU grep/egrep、 Tcl


总结:

其实从定义上很容易区分DFA和NFA。DFA的下一个可能状态是唯一确定的,但是NFA则不然,它有多个可能的状态。尽管DFA和NFA有不同的定义,但在形式理论中可以证明它们是等价的。就是说,对于任何给定的NFA都可以构造一个等价的DFA。

分享到:
评论

相关推荐

    词法程序设计——DFA模拟程序

    (2)将NFA化为DFA (3)输入一个字符串判断是否符合文法。 ①最开始记A为开始状态a为第一个字符。 ②然后A经过字符a到达下一个状态记为B,A状态指向B状态,a指向字符串的下一个字符。 ③循环②步直到B状态为终态时...

    nfa--dfa.rar_DFA_NFA DFA_NFA转DFA

    -dfa.rar_DFA_NFA DFA_NFA转DFA”提到了两种类型的状态自动机:非确定性有限状态自动机(Non-Deterministic Finite Automaton,简称NFA)和确定性有限状态自动机(Deterministic Finite Automaton,简称DFA)。...

    编译原理——模拟实现DFA/NFA

    学习一门简单的程序设计语言的定义及其编译器实现 针对一门简单的程序设计语言,阅读其定义文档,初步了解其...通过本次实验,加深对DFA/NFA及其识别的语言的理解,学习对一般的DFA/NFA的表达方法与编程实现方法。

    nfa_dfa.rar_DFA_NFA DFA _NFA DFA_automata_nfa

    这里提到的两种类型是确定性有限自动机(Deterministic Finite Automaton,DFA)和非确定性有限自动机(Non-deterministic Finite Automaton,NFA)。这两种自动机都是形式语言理论的核心部分,广泛应用于编译器设计...

    NFA到DFA.rar_NFA DFA_NFA到DFA转换_nfa and dfa pdf_nfa-dfa_nfa,dfa

    在计算机科学领域,正则表达式和自动机理论是编译原理的重要组成部分,其中NFA(非确定性有限状态自动机)和DFA(确定性有限状态自动机)是两种核心概念。NFA到DFA的转换是一个重要的理论与实践问题,尤其是在编译器...

    NFAtoDFA.rar_DFA_NFA DFA_NFA to DFA_nfa

    FSA)是一种重要的概念,主要分为两种类型:确定性有限状态自动机(Deterministic Finite Automaton, DFA)和非确定性有限状态自动机(Non-Deterministic Finite Automaton, NFA)。本压缩包文件“NFAtoDFA.rar”...

    NFA.rar_DFA_NFA DFA_NFA to DFA_mklianfa1.r_nfa

    从NFA的矩阵表示中可以看出,表项通常是一状态的集合,而在DFA的矩阵表示中,表项是一个状态,NFA到相应的DFA的构造的基本思路是:1.DFA的每一个状态对应NFA的一组状态. 2. DFA使用它的状态去记录在NFA读入一个输入...

    NFA-DFA.rar_DFA_NFA DFA_NFA to DFA_nfa

    其中,NFA(Non-Deterministic Finite Automaton,非确定性有限状态自动机)和DFA(Deterministic Finite Automaton,确定性有限状态自动机)是两种常见的类型。本主题主要围绕如何将NFA转换为DFA,这是编译原理和...

    nfa-dfa.rar_DFA_Dfa Nfa_NFA DFA_NFA DFA c++_nfa

    在阅读和理解这段代码时,应重点关注数据结构的设计、状态转换的实现以及如何从NFA状态到DFA状态的映射。通过对代码的分析,我们可以更直观地了解NFA到DFA转换的具体步骤和细节。 总结来说,NFA和DFA是自动机理论中...

    DFA&NFA的代码

    在编程实现DFA和NFA时,通常会用到数据结构来表示状态和转换关系。例如,状态可以用整数标识,状态间的转移可以存储在一个二维数组或者哈希表中,其中键是当前状态和输入符号,值是下一个状态的集合。对于NFA,由于...

    实验一 简单的词法设计——DFA模拟程序.docx

    实验一的目的是让学生深入理解编译的理论知识,特别是词法分析部分,通过编写DFA(有穷确定自动机)模拟程序,增强学生的实践能力和综合应用能力。在实验环境中,学生可以使用C++、C#或Java等编程语言在Windows系统...

    NFA到DFA的转化程序

    在编译原理中,NFA(非确定有限状态自动机)和DFA(确定有限状态自动机)是两种重要的计算模型,广泛应用于正则表达式和形式语言的处理。本主题将深入探讨如何将NFA转换为DFA,并通过一个Java实现的程序来展示这一...

    DFA.rar_DFA_Dfa Nfa_NFA DFA_nfa_nfa确定化

    标题中的"DFA.rar"和"NFA"分别代表两种类型的有限状态自动机:确定有限状态自动机(Deterministic Finite Automaton,DFA)和非确定有限状态自动机(Non-deterministic Finite Automaton,NFA)。这些概念在编译原理...

    编译原理DFA_NFA

    这个主题涵盖了许多概念和技术,其中包括确定性有限自动机(Deterministic Finite Automaton, DFA)和非确定性有限自动机(Non-deterministic Finite Automaton, NFA)。在这个万海课程作业中,我们将深入探讨这两个...

    NFA到DFA的转换

    尽管DFA在某些情况下可能不如NFA高效,但它们更易于理解和实现,同时也更容易进行状态最小化。 **NFA到DFA的转换** NFA到DFA的转换是一种构造过程,目的是将一个非确定性的自动机转换成一个确定性的自动机,同时...

    DFA,NFA实现

    NFA与DFA类似,但允许在接收到输入时有多个可能的下一步状态。这使得NFA可以比DFA更简洁地表示某些语言,因为它们可以有多个“猜测路径”。NFA的一个核心特性是ε-转移,即无需输入字符就可以进行状态转换。 3. **...

    NFAtoDFA.zip_NFA DFA_NFA转DFA_nfa转化

    然而,NFA在实际应用中存在一些不便,例如在算法实现时可能需要进行多次路径探索,这在效率上可能不如DFA。DFA在每个状态下只有一个可选的转移,因此它的执行过程是确定且单路径的,这使得DFA在实现上更加简单和高效...

    NFA-to-DFA.rar_DFA NFA_NFA DFA_nfa

    在计算机科学领域,尤其是形式语言和自动机理论中,NFA(非确定性有限状态自动机)和DFA(确定性有限状态自动机)是两种重要的模型,用于描述和识别字符串的语言。本实验主要探讨如何将一个NFA转换为DFA,这是一项...

    正则引擎:DFA和NFA.rar

    NFA 与 DFA 相比,允许在某个状态下对多个可能的下一步进行并行探索,即对于输入字符,可能存在多个可能的转移。NFA 可以通过ε-转移(无字符输入的状态转移)来实现正则表达式的“或”和“重叠”特性。NFA 的构建...

    DFA_NFA_MFA.rar_NFA DFA MFA_nfa

    在计算机科学领域,编译器是将高级编程语言转换为机器可执行代码的关键工具。编译原理是研究这种转换过程的理论基础,...对于计算机科学的学生和专业开发者来说,深入掌握DFA、NFA和MFA的理论与实践是不可或缺的技能。

Global site tag (gtag.js) - Google Analytics