Regex 如何使用字符范围实现正则表达式NFA?

Regex 如何使用字符范围实现正则表达式NFA?,regex,dfa,nfa,Regex,Dfa,Nfa,当你读到这样的帖子时,一切看起来都很简单,直到你意识到在现实生活中,你不仅需要像“7”或“b”这样的直接字符,还需要: [A-Z] [^_] . 即字符类(或范围)。因此我的问题是——如何使用字符范围构建NFA?使用诸如“不是A”、“其他任何东西”之类的元字符,然后计算重叠范围?这将导致在使用最终自动机时使用树状结构,而不仅仅是一个表 更新:请假设字母表大小不小(>>256) 我问的是NFA,但后来我也想将NFA转换为DFA。最简单的方法是: 使用段作为NFA和DFA中过渡的标签。例如,范围[

当你读到这样的帖子时,一切看起来都很简单,直到你意识到在现实生活中,你不仅需要像“7”或“b”这样的直接字符,还需要:

[A-Z]
[^_]
.
即字符类(或范围)。因此我的问题是——如何使用字符范围构建NFA?使用诸如“不是A”、“其他任何东西”之类的元字符,然后计算重叠范围?这将导致在使用最终自动机时使用树状结构,而不仅仅是一个表

更新:请假设字母表大小不小(>>256)


我问的是NFA,但后来我也想将NFA转换为DFA。

最简单的方法是:

  • 使用段作为NFA和DFA中过渡的标签。例如,范围[a-z]将被重新呈现为段
    [97122]
    ;单个字符“a”将变成
    [97,97]
    ;任何字符“.”都将变成
    [minCode,maxCode]

  • 每个否定范围[^a-z]将导致从开始状态到下一状态的两次转换。在本例中,应创建两个转换
    [minCode,96]
    [123,maxCode]

  • 当范围通过枚举所有可能的字符[abcz]来表示时,应该创建每个字符的转换,或者代码将第一个字符分组到范围中,以优化转换的数量。因此[abcz]将变成
    [a-c]| z
    。因此,两次转变而不是四次

  • 这对NFA来说应该足够了。但是,当存在具有相交字符范围的转换时,将NFA转换为DFA的经典方法将不起作用。 要解决这个问题,只需要一个额外的泛化步骤。一旦一组输入符号被创建,在我们的例子中,它将是一组段,它应该被转换成一组不相交的段。这可以在时间O(n*Log(n))中完成,其中n是使用优先级等式(PQ)的集合中的段数,其中段由左分量排序。例如:

      Procedure DISJOIN:
       Input  <- [97, 99] [97, 100] [98, 108]
       Output -> [97, 97] [98, 99], [100, 100], [101, 108]
    
    过程分离:
    输入[97,97][98,99],[100100],[101108]
    
    第2步。要从“设置状态”创建新的转换,应修改算法,如下所示:

       for each symbol in DISJOIN(input symbols)
         S <- empty set of symbols
         T <- empty "set state"
         for each state in "set state"
          for each transition in state.transitions
            I <- intersection(symbol, transition.label) 
            if (I is not empty)
            {
               Add I to the set S
               Add transition.To to the T
            }       
    
         for each segement from DISJOIN(S)
            Create transition from "set state" to T
    
    用于分离中的每个符号(输入符号)
    
    请澄清“使用字符范围构建NFA”的意思@revo,使用
    标记边缘,即如果输入为
    j
    ,则使用此标签,但如果输入为
    z
    ,则不使用此标签。这并不难,但是有几个重叠的标签(
    h
    )会造成混乱。我不喜欢重新发明轮子,所以我在问。这一切都取决于你如何表现边缘。对于8位字符集,考虑256位的位图。如果设置了位n,则字符代码n在允许的范围内,例如。@tripleee,谢谢。我认为8位在实践中不会再流行了,Unicode更有可能。但这意味着每个标签8 KB(!)。这种方法是否用于任何公开的程序中,或者只是理论上的想法?如果您真的需要支持Unicode,那么还需要考虑一系列其他因素。请参阅关于regex支持的说明。同时,也许只考虑以一种合理的方式支持UTF-8。