【问题标题】:Algorithm to see if regex repeat is reducible查看正则表达式重复是否可减少的算法
【发布时间】:2012-06-25 02:04:53
【问题描述】:

我正在寻找一种算法来检查嵌套的正则表达式重复是否可减少。假设解析正则表达式已经完成。

示例:

(1{1,2}){1,2} === 1{1,4}
    It matches 1, 11, 111, 1111 which can be rewritten as a single repeat

(1{2,2}){1,2} can not be reduced
    It matches 11 and 1111 which can not be rewritten as a single repeat.

(1{10,11}){1,2} can not be reduced

(1{10,19}){1,2} === 1{10,38}

(1{1,2}){10,11} === 1{10,22}

(1{10,11})* can not be reduced

(1*){10,11} === 1*

我一直在尝试为这种类型的操作找到一种模式,而不必匹配所有可能的解决方案并寻找可以防止它被减少的漏洞。必须有一个简单的函数 (f( A, B, C, D ) -> ( E, F )) 可以解决这样的任意输入:

(1{A,B}){C,D} -> 1{E,F}

【问题讨论】:

  • 注意:(1{1,2}){1,2} 只匹配 1, 11, 11, 1111 所以 !== 1{1,4};也可以先将(1{2,2}){1,2} 缩减为(1{2}){1,2},然后再缩减为11{1,2};同样(1{10,19}){1,2} 不等于1{10,38},因为1{21}...1{37} 范围内的赔率不能以“长格式”表示(例如,(1{10.5}){2} 是不可能的)
  • @kaᵠ 这不是真的。 (1{1,2}){1,2} 完全等同于 1{1,4}。这是因为第一组的重复允许在使用之间进行更改。 (1{1,2}){1,2} === (1{1,2})(1{1,2})? === (1{1,2})(1{0,2}) === 11?1?1? === 1{1,4}.不信就试试看:)

标签: regex algorithm language-agnostic


【解决方案1】:
// (x{A,B}){C,D} -> x{E,F}
bool SimplifyNestedRepetition(int A, int B,
                              int C, int D,
                              out int E, out int F)
{
    if (B == -1 || C == D || A*(C+1) <= B*C + 1)
    {
        E = A*C;

        if (B == -1 || D == -1) F = -1;
        else F = B*D;

        return true;
    }
    return false;
}
  • 如果x{A,B} 不受限制,则可以重复任意次数。
  • (x{A,B}){C} 总是可约化的。
  • 如果A*(C+1) &lt;= B*C + 1,你可以减少它,因为C重复的最长序列和C+1重复的最短序列之间没有差距。

B = -1D == -1 表示无限制,如x*x{5,}


测试用例:

Input           Reducible?
(x{0,0}){0,0}   Yes - x{0,0}
(x{0,1}){0,0}   Yes - x{0,0}
(x{0,2}){0,0}   Yes - x{0,0}
(x{1,1}){0,0}   Yes - x{0,0}
(x{1,2}){0,0}   Yes - x{0,0}
(x{1,3}){0,0}   Yes - x{0,0}
(x{2,2}){0,0}   Yes - x{0,0}
(x{2,3}){0,0}   Yes - x{0,0}
(x{2,4}){0,0}   Yes - x{0,0}
(x{0,0}){0,1}   Yes - x{0,0}
(x{0,1}){0,1}   Yes - x{0,1}
(x{0,2}){0,1}   Yes - x{0,2}
(x{1,1}){0,1}   Yes - x{0,1}
(x{1,2}){0,1}   Yes - x{0,2}
(x{1,3}){0,1}   Yes - x{0,3}
(x{2,2}){0,1}   No 
(x{2,3}){0,1}   No 
(x{2,4}){0,1}   No 
(x{0,0}){0,2}   Yes - x{0,0}
(x{0,1}){0,2}   Yes - x{0,2}
(x{0,2}){0,2}   Yes - x{0,4}
(x{1,1}){0,2}   Yes - x{0,2}
(x{1,2}){0,2}   Yes - x{0,4}
(x{1,3}){0,2}   Yes - x{0,6}
(x{2,2}){0,2}   No 
(x{2,3}){0,2}   No 
(x{2,4}){0,2}   No 
(x{0,0}){1,1}   Yes - x{0,0}
(x{0,1}){1,1}   Yes - x{0,1}
(x{0,2}){1,1}   Yes - x{0,2}
(x{1,1}){1,1}   Yes - x{1,1}
(x{1,2}){1,1}   Yes - x{1,2}
(x{1,3}){1,1}   Yes - x{1,3}
(x{2,2}){1,1}   Yes - x{2,2}
(x{2,3}){1,1}   Yes - x{2,3}
(x{2,4}){1,1}   Yes - x{2,4}
(x{0,0}){1,2}   Yes - x{0,0}
(x{0,1}){1,2}   Yes - x{0,2}
(x{0,2}){1,2}   Yes - x{0,4}
(x{1,1}){1,2}   Yes - x{1,2}
(x{1,2}){1,2}   Yes - x{1,4}
(x{1,3}){1,2}   Yes - x{1,6}
(x{2,2}){1,2}   No 
(x{2,3}){1,2}   Yes - x{2,6}
(x{2,4}){1,2}   Yes - x{2,8}
(x{0,0}){1,3}   Yes - x{0,0}
(x{0,1}){1,3}   Yes - x{0,3}
(x{0,2}){1,3}   Yes - x{0,6}
(x{1,1}){1,3}   Yes - x{1,3}
(x{1,2}){1,3}   Yes - x{1,6}
(x{1,3}){1,3}   Yes - x{1,9}
(x{2,2}){1,3}   No 
(x{2,3}){1,3}   Yes - x{2,9}
(x{2,4}){1,3}   Yes - x{2,12}
(x{0,0}){2,2}   Yes - x{0,0}
(x{0,1}){2,2}   Yes - x{0,2}
(x{0,2}){2,2}   Yes - x{0,4}
(x{1,1}){2,2}   Yes - x{2,2}
(x{1,2}){2,2}   Yes - x{2,4}
(x{1,3}){2,2}   Yes - x{2,6}
(x{2,2}){2,2}   Yes - x{4,4}
(x{2,3}){2,2}   Yes - x{4,6}
(x{2,4}){2,2}   Yes - x{4,8}
(x{0,0}){2,3}   Yes - x{0,0}
(x{0,1}){2,3}   Yes - x{0,3}
(x{0,2}){2,3}   Yes - x{0,6}
(x{1,1}){2,3}   Yes - x{2,3}
(x{1,2}){2,3}   Yes - x{2,6}
(x{1,3}){2,3}   Yes - x{2,9}
(x{2,2}){2,3}   No 
(x{2,3}){2,3}   Yes - x{4,9}
(x{2,4}){2,3}   Yes - x{4,12}
(x{0,0}){2,4}   Yes - x{0,0}
(x{0,1}){2,4}   Yes - x{0,4}
(x{0,2}){2,4}   Yes - x{0,8}
(x{1,1}){2,4}   Yes - x{2,4}
(x{1,2}){2,4}   Yes - x{2,8}
(x{1,3}){2,4}   Yes - x{2,12}
(x{2,2}){2,4}   No 
(x{2,3}){2,4}   Yes - x{4,12}
(x{2,4}){2,4}   Yes - x{4,16}

【讨论】:

  • 这不是 100% 正确的。例如(x{2,5}){2} 给出x{4,10},但原始模式无法匹配xs 的奇数。另一个例子是(x{y,z}){1},它总是可以简化为x{y,z}
  • “无法匹配奇数”——当然可以。相当于x{2,5}x{2,5}。您不必在两个子模式中选择相同的出现次数。使用echo xxxxxxx | egrep '(x{2,5}){2}' 进行检查。
  • @n.m.不知道我在想什么:)
【解决方案2】:

如果您没有使用反向链接等“高级”正则表达式功能,那么正则表达式只是有限状态自动机,是状态机的简单版本。它们有一个非常好的特性,即对于所有 FSA,都存在一个独特的最小的 FSA,甚至很容易找到它:Wikipedia

虽然您的问题看起来更具体,但我相信看看其中描述的一些最小化算法会很有用。

【讨论】:

  • 我实际上已经在我正在研究的库中做这种类型的东西,但是这种类型的操作是方式昂贵的。从正则表达式转换 -> NFA -> DFA 是 2^n
  • 在我的情况下,我正在尝试制作一个优化器来获取 DFA 并输出一个正则表达式,但通常我最终会得到类似这个问题中的模式,我想输出尽可能小的正则表达式.
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-02
  • 1970-01-01
  • 2019-08-30
  • 2016-04-16
  • 2011-08-19
  • 2017-12-27
相关资源
最近更新 更多