Почему класс персонажей быстрее чередования?

Кажется, что использование класса символов быстрее, чем чередование в примере, подобном следующему:
[abc] против (a|b|c)
Я слышал о том, что это рекомендуется и с помощью простого теста с использованием Time::HiRes Я это проверил (примерно в 10 раз медленнее).
Также используя (?:a|b|c) в случае, если вводимые скобки имеют значение, результат не меняется.
Но я не могу понять, почему. Я думаю, что это из-за обратного отслеживания, но, как я вижу в каждой позиции, есть сравнение трех символов, поэтому я не уверен, как обратный путь влияет на чередование. Это результат чередования реализации?

2 ответа

Это потому, что конструкция "ИЛИ" | возвраты между чередованием: если первое чередование не сопоставлено, двигатель должен вернуться до того, как указатель переместится во время совпадения чередования, чтобы продолжить сопоставление следующего чередования; Принимая во внимание, что класс персонажа может продвигаться последовательно. Посмотрите это совпадение на движке регулярных выражений с отключенной оптимизацией:

Pattern: (r|f)at
Match string: carat

alternations

Pattern: [rf]at
Match string: carat

class


Но если быть кратким, то, что движок pcre оптимизирует это (отдельные литеральные символы -> класс символов), уже является приличным намеком на то, что чередования неэффективны.

Потому что класс персонажей, как [abc] является неснижаемым и может быть оптимизирован, в то время как чередование, как (?:a|b|c) также может быть (?:aa(?!xx)|[^xba]*?|t(?=.[^t])t),

Авторы решили не оптимизировать компилятор регулярных выражений, чтобы проверить, что все элементы чередования являются одним символом.

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

Другие вопросы по тегам