例如,正则表达式go*d
是一个模式将匹配字符串,如gd
, god
, good
...
你可以想象它的 DFA 就像一个三态机。
当它用于模式搜索时,例如给定句子xxxxgodxxxxgoodxxx
,DFAgo*d
似乎不起作用。x
在这个三态 DFA 中,偶数字符是未定义的。
我们可以想象一个带有额外“重置”状态的 4 状态 DFA 可以在这里工作。也就是说,当遇到未定义的字符时,进入这个“重置”状态。
问题是模式搜索工具如何使用正则表达式实现搜索目的go*d
?
例如,正则表达式go*d
是一个模式将匹配字符串,如gd
, god
, good
...
你可以想象它的 DFA 就像一个三态机。
当它用于模式搜索时,例如给定句子xxxxgodxxxxgoodxxx
,DFAgo*d
似乎不起作用。x
在这个三态 DFA 中,偶数字符是未定义的。
我们可以想象一个带有额外“重置”状态的 4 状态 DFA 可以在这里工作。也就是说,当遇到未定义的字符时,进入这个“重置”状态。
问题是模式搜索工具如何使用正则表达式实现搜索目的go*d
?
给定简单的三态匹配器
|start|---/g/---+->|S1|-->-+---/d/--->|accept|
| |
+--<-/o/-<-+
您不需要重置状态,而是需要在开始状态上标记为[^g]
. 严格遵循 dfa 定义,您需要|Σ|-1
每个转换都标有一个字母字符,而不是g
. 同样,从标记S1
到start
标记[^g]
以及从标记S1
到自身的转换g
保证在遇到模式可能实例化的前缀后正确“重置”。类似地增强accept
状态,您将捕获所有非重叠模式实例化(它们都是此特定模式的所有实例化。
当然,这很快变得比这个玩具示例复杂得多,这就是为什么通常使用标准的 regex->nfa->dfa 构造。
另一种策略是在没有增强的情况下使用您的原始 dfa,并在您每次离开该start
州时生成一个子进程。子进程应用与其父进程相同的 dfa,将其应用于以使转换离开起始状态的字符开头的给定句子。