这个
article表明在回溯时有一些正则表达式为O(2 ^ n).
例子是(x x)y.
当尝试匹配像xxxx …这样的字符串时,它会回溯一段时间,然后才发现它无法匹配.
例子是(x x)y.
当尝试匹配像xxxx …这样的字符串时,它会回溯一段时间,然后才发现它无法匹配.
有没有办法检测这样的正则表达式?
谢谢
如果你的正则表达式引擎暴露了(x x)y的运行时指数行为,那么它就会被破坏,因为DFA或NFA可以在线性时间内识别出这种模式:
echo "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" | egrep "(x+x+)+y" echo "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxy" | egrep "(x+x+)+y"
都立即回答.
实际上,只有少数情况(如反向引用)确实需要回溯(主要是因为具有反向引用的正则表达式不再是语言理论意义上的正则表达式).只有在给出这些极端情况时,有能力的实现才应切换到回溯.
公平地说,DFA也有一个黑暗的一面,因为一些正则表达式具有指数大小要求,但是尺寸约束比时间约束更容易实施,并且巨大的DFA在输入上运行线性,因此它比小型回溯窒息更便宜在几个X的.
你应该阅读关于regexp(以及回溯的病理行为)的实现的Russ Cox优秀文章系列:http://swtch.com/~rsc/regexp/
要回答关于可判定性的问题:你做不到.因为regexpr没有一个回溯.每个实现都有自己的策略来处理某些情况下算法的指数增长,而不涉及其他情况.一条规则可能适合这里,也可能是灾难性的.
更新:
例如,一个实现可以包含一个优化器,它可以在执行它们之前使用代数转换来简化正则表达式:(x x)y与xxx * y相同,这对于任何回溯都不应该是一个问题.但是同样的优化器不会识别下一个表达式,问题又出现了.在这里有人描述了如何制作一个愚弄Perl优化器的regexpr:
http://perlgeek.de/blog-en/perl-tips/in-search-of-an-exponetial-regexp.html