【问题标题】:Why use NFAs over DFAs为什么使用 NFA 而不是 DFA
【发布时间】:2015-10-21 13:40:33
【问题描述】:

我目前正在研究一些计算理论,正如所暗示的那样,这是非常理论化的。

我可以很容易地从正则表达式转换为 NFA 到 DFA,我可以理解。

但是由于所有 NFA 都可以转换为 DFA,并且(我很确定)UNIX 中的grep 命令使用正则表达式来确定匹配字符串,所以最常用的有限自动机、DFA 或 NFA 是什么?

根据我的经验(不多),在表示常规语言时,DFA 通常更易于使用,并且具有确定性,因此应始终选择 NFA。

NFA 分支到多个结果,需要递归函数,而且对我来说似乎更尴尬。

我知道编译器是有限自动机的另一种实际用途。

我的问题...为什么要同时学习/使用两者。 DFA 在我看来完全没问题。

感谢您的任何回答!

【问题讨论】:

标签: regex dfa computation-theory compiler-theory nfa


【解决方案1】:

DFA 通常更快且更具可扩展性。确定和最小化 NFA 有时代价高昂。所以如果自动机只使用一次就可以跳过。

NFA(Thompson-NFA、Glushkov-NFA、位并行 NFA)的优点是:

  • 它们可以更简洁地表达
  • 他们可以记录子匹配(例如,用于正则表达式替换)
  • 它们可以即时转换为非最小化 DFA

此外,常用编程语言中使用的 Regex-NFA(Backtracking-NFA,例如 Python、Perl、Java、.NET,而不是 grep):

  • 甚至比上层 NFA 还要慢
  • 支持贪婪、非贪婪和占有模式
  • 但可以使用lookaheads/lookbehinds
  • 并且可以使用反向引用(这些不能转换为 DFA)

编译器几乎总是使用最小化的 DFA 进行词法分析。正则表达式搜索使用 DFA 或混合 DFA/NFA(后者用于子匹配识别)。编程语言中使用的 NFA 是最强大的(就功能而言),但也是最慢的。

【讨论】:

  • 可能会补充一些表示为 DFA 的常规语言会导致状态爆炸,例如一些未绑定的匹配
  • 还可以进行资源权衡。确定和最小化可能是时间和内存密集型的,因此只有在生成的自动机将被大量使用时才有意义。
  • 我在答案中添加了资源权衡。我是对的,第一条评论指的是 DFA 状态仅受 O(2^n) 限制,其中 n 是 NFA 中的状态数?
【解决方案2】:

我认为将回归转换为 NFA 比 DFA 更简单。很难直接将回归转换为 DFA。

【讨论】:

    猜你喜欢
    • 2011-08-16
    • 2013-01-28
    • 1970-01-01
    • 1970-01-01
    • 2011-01-02
    • 2010-11-23
    • 2019-03-14
    • 1970-01-01
    相关资源
    最近更新 更多