Правильная скобочная последовательность

Материал из testwiki
Версия от 19:13, 19 ноября 2023; imported>Immurz (Добавлен пример генерации ПСП на PHP, дополнение)
(разн.) ← Предыдущая версия | Текущая версия (разн.) | Следующая версия → (разн.)
Перейти к навигации Перейти к поиску

Пра́вильная ско́бочная после́довательность (ПСП) — символьная последовательность, составленная в алфавите, состоящем из символов, сгруппированных в упорядоченные пары (типы скобок, графически обозначаемые "(" и «)», "[" и «]», «/*» и «*/» и т. п.), удовлетворяющая определённым правилам, обеспечивающим последовательную вложенность подпоследовательностей, обрамлённых открытой и закрытой скобкой одного типа.

Правильные скобочные последовательности образуют язык Дика и формально определяются следующим образом:

  • пустая строка — правильная скобочная последовательность;
  • правильная скобочная последовательность, взятая в скобки одного типа — правильная скобочная последовательность;
  • правильная скобочная последовательность, к которой приписана слева или справа правильная скобочная последовательность — тоже правильная скобочная последовательность.

Число правильных скобочных последовательностей

Число правильных скобочных последовательностей из 2n скобок (n открывающих и n закрывающих) одного вида равно числу Каталана Cn, что можно вывести несколькими способами:

C0=1 и Cn=i=0n1CiCn1i для n1.

Это соотношение легко получить, заметив, что любая непустая правильная скобочная последовательность ω однозначно представима в форме ω=(ω1)ω2, где ω1,2 — правильные скобочные последовательности.

Cn=1n+1(2nn)=(2n)!n!(n+1)!=(2nn)(2nn1).
  • Ещё одно рекуррентное соотношение:
R(o,n)={1,o=0andn=0;0,n=0oro>noro<0;R(o+1,n1)+R(o1,n1),otherwise.

При этом Cn=R(0,2n).

Легко показать, что если в скобочной последовательности имеется k типов скобок, то число возможных правильных скобочных последовательностей с n открывающими скобками равно произведению Cn на kn. Действительно, для каждой открывающей скобки из n существует k различных вариантов её выбора. Выбор закрывающей скобки однозначно определён уже выбранной парной ей открывающей и не учитывается.

Генерация правильных скобочных последовательностей

Введём теперь лексикографический порядок на скобочных последовательностях. В первую очередь заметим, что открывающая скобка идёт раньше, чем закрывающая; так как скобочная последовательность, начинающаяся с закрывающей скобки, не является правильной. Теперь каждому из k типов скобок присвоим свой лексикографический приоритет. Выбор этого приоритета не принципиален и ни на что не повлияет в ходе дальнейших рассуждений. Поэтому будем считать, что iй тип скобок находится на iй позиции в лексикографическом порядке. Очевидно, что первой последовательностью с n открывающими скобками будет последовательность вида (1(1...(1)1)1...)1.

Шаблон:Rq

Пример рекурсивной реализации алгоритма генерации ПСП на PHP

<?php

function generateBracketsSequence(
    int $length,
    int $countOpenBrackets = 0,
    int $countCloseBrackets = 0,
    string $sequence = '',
): void {

    if (mb_strlen($sequence) < $length * 2) {

        if ($countOpenBrackets < $length) {
            generateBracketsSequence(
                $length,
                $countOpenBrackets + 1,
                $countCloseBrackets,
                $sequence . '(',
            );
        }

        if ($countCloseBrackets < $countOpenBrackets) {
            generateBracketsSequence(
                $length,
                $countOpenBrackets,
                $countCloseBrackets + 1, 
                $sequence . ')',
            );
        }

    } else {
        echo $sequence.' - '."\r\n";
    }

}

generateBracketsSequence(4);