Почему так /? (.+) +Q$/.test("XXXXXXXXXXXXXXXXXXXXXXXXXXXX?) Занимает так много времени?

Когда я запустил

/^(.+)+Q$/.test("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX")

в Chrome или IE, требуется ~ 10 секунд. (Firefox может оценить его почти мгновенно.)

Почему так долго? (И почему/как Firefox может сделать это так быстро?)

(Конечно, я никогда не буду запускать это конкретное регулярное выражение, но я сталкиваюсь с аналогичной проблемой с URL-адресом regex в http://daringfireball.net/2010/07/improved_regex_for_matching_urls, и, похоже, сводятся к этому, т.е. есть определенные URL-адреса, которые заставят браузер заблокировать)

Например:

var re = /\b((?:https?:\/\/|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»""‘’]))/i;
re.test("http://google.com/?q=(AAAAAAAAAAAAAAAAAAAAAAAAAAAAA")

Ответ 1

Как указано в thg435, это звучит как катастрофическое обратное отслеживание. Там отличная статья об этом, Регулярное соответствие выражению может быть простым и быстрым.

В нем описывается эффективный подход, известный как NOM Томпсон. Как уже отмечалось, это не поддерживает все функции современных регулярных выражений. Например, он не может делать обратные ссылки. Однако, как было предложено в статье:

"Несмотря на это, было бы разумно использовать имитацию Thompson NFA для большинство регулярных выражений, и только вывести назад, когда это необходимо. Особенно умная реализация могла бы объединить два, прибегая к отступлению только для размещения обратных ссылок".

Я подозреваю, что Firefox может это сделать.