Как этот PCRE паттерн обнаруживает палиндромы?

Этот вопрос является образовательной демонстрацией использования предпросмотра, вложенных ссылок и условных выражений в шаблоне PCRE для соответствия ВСЕМ палиндромам, включая те, которые не могут быть сопоставлены с рекурсивным шаблоном, приведенным на справочной странице PCRE.

Изучите этот шаблон PCRE в фрагменте PHP:

$palindrome = '/(?x)
^
  (?:
      (.) (?=
              .*
              (
                \1
                (?(2) \2 | )
              )
              $
          )
  )*
  .?
  \2?
$


/';

Этот паттерн, кажется, обнаруживает палиндромы, как видно из этого теста (смотрите также на ideone.com):

$tests = array(
  # palindromes
  '',
  'a',
  'aa',
  'aaa',
  'aba',
  'aaaa',
  'abba',
  'aaaaa',
  'abcba',
  'ababa',

  # non-palindromes
  'aab',
  'abab',
  'xyz',
);

foreach ($tests as $test) {
  echo sprintf("%s '%s'\n", preg_match($palindrome, $test), $test);  
}

Так как же работает этот шаблон?

Заметки

Этот шаблон используетвложенная ссылка, который является аналогичным методом, используемым вКак это регулярное выражение Java обнаруживает палиндромы?, но в отличие от этого шаблона Java, нет никакого взгляда назад (но он используетусловный).

Также обратите внимание, что PCREсправочная страница представляет рекурсивный шаблон для соответствия некоторым палиндромам:

# the recursive pattern to detect some palindromes from PCRE man page
^(?:((.)(?1)\2|)|((.)(?3)\4|.))$

Страница man предупреждает, что этот рекурсивный шаблон НЕ может обнаружить все палиндромы (см .:Почему это рекурсивное регулярное выражение совпадает только тогда, когда персонаж повторяет 2n - 1 раз? а такжетакже на ideone.com), но вложенная справочная / позитивная прогнозная картина, представленная в этом вопросе, может.

Ответы на вопрос(1)

Ваш ответ на вопрос