Как вы, возможно, знаете, существует два разных типа реализаций регулярных выражений: одна использует возвратный путь (pcre), а другая - конечные автоматы (re2).
Оба этих алгоритма имеют свои ограничения: в определенных случаях pcre может потребоваться экспоненциальное время для поиска соответствия, а конечные автоматы не поддерживают обратные ссылки.
Реализация Pcre поддерживает обратные ссылки, очень неэффективные в сопоставлении выражений, таких как /a?a?a?a?aaaa/
с aaaa
, чем больше выражение и ввод a
имеют - тем дольше это займет, а с 30+ из них это займет много если время.
Версия с конечными автоматами прекрасно справляется со всеми этими реализациями и имеет O (N)
сложность ввода, но не поддерживает обратные ссылки:
пкр времени против сложных выражений - http://i.stack.imgur.com/D4gkC.png
NFA обрабатывает их, но не поддерживает обратные ссылки - http://i.stack.imgur.com/t2EwI.png
Некоторая информация о поддержке обратных ссылок:
RE2 - http://code.google.com/p/re2/
Единственное существенное исключение состоит в том, что RE2 прекращает поддержку обратных ссылок и обобщенных утверждений нулевой ширины, поскольку они не могут быть эффективно реализованы .
Томпсон НФА - http://swtch.com/~rsc/regexp/regexp1.html
Как упоминалось ранее, никто не знает, как эффективно реализовать регулярные выражения с обратными ссылками , хотя никто не может доказать, что это также невозможно. (В частности, проблема в том, что NP-полная, то есть если кто-то найдет эффективную реализацию, это станет важной новостью для компьютерных ученых и выиграет приз в миллион долларов.)
Итак, я создал свою собственную версию, которая поддерживает обратные ссылки и имеет сложность O (N). Он написан на языке Haskell и содержит около 600 строк (из них ~ 200 пустых и объявления типа ~ 200, которые можно пропустить). Он пережевывает /a?a?aa/
против aa
(с 100 a
) примерно за 10 секунд, и, насколько я знаю, это единственная версия, которая может соответствовать
/a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?(a?a?a?a?a?a?a?a?a?a?aaaaaaaaaa)aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\1/
против
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
в нормальное (около 10 секунд) время. Конечно, он поддерживает все другие функции, перечисленные в базовой спецификации регулярных выражений, которые я нашел где-то в Интернете.
Вопрос в том, действительно ли это "главная новость для компьютерных ученых" и что мне делать, если это так?
PS: я покажу источники примерно через неделю - я все еще хочу запустить некоторые тесты с профилировщиком и заменить несколько внутренних структур данных.