Изменения

Перейти к: навигация, поиск

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

2993 байта убрано, 02:44, 15 января 2012
Нет описания правки
*"" (пустая строка) есть правильная скобочная последовательность;
*пусть $S$ - правильная скобочная последовательность, взятая в скобки тогда $(S)$ есть правильная скобочная последовательность;(*)*пусть $S$ - правильная скобочная последовательность, к которой приписана слева или справа другая правильная скобочная последовательность, тогда $()S$ и $S()$ есть правильная скобочная последовательностьправильные скобочные последовательности;
}}
''Примеры правильных скобочный последовательностей:''
''псевдокод'':
function bool check(s: string): boolean; var i, a :integer; begin a :pointer = 0 for (i := 1 to ; i < length(s) do {перебираем последовательно все символы строки (подразумевается, что в ней нет символов отличных от "(" и "+ 1; i++)")}: begin if pointer = (s[i] == '(' then {проверяем символ и производим соответствующие действия над переменной a} inc(a)? pointer++ : pointer-- else dec if (a); if a pointer < 0 then) check := return false; end; if a (pointer = 0 then {проверяем на равенство нулю}) check := return true else check := return false; end;
Надо отметить что, скобочные последовательности могут состоять не только из одного типа скобок, при этом недопустимо такое расположение, когда один тип скобок закрывает другой:
== Лексикографический порядок порядок правильных скобочных последовательностей ==
Для того чтобы определить лексикографический порядок для правильных скобочных последовательностей будем интерпретировать открывающуюся скобку как "$0$"надо установить порядок на алфавите, а закрывающуюся как "например так '$1$" (**). Тогда первая последовательность с $n' < '$ открывающимися скобками будет иметь вид: {| border="1" cellpadding="3" | (||(||(||(||...||(||(||(||)||)||)||...||)||)||)||)||(***) |- |0||0||0||0||...||0||0||0||1||1||1||...||1||1||1||1 |} что соответствует самому маленькому возможному числу, а последняя: {| border="1" cellpadding="3" | (||)||(||)||...||(||)||(||)||(||)||...||(||)||(||) |- |0||1||0||1||...||0||1||0||1||0||1||...||0||1||0||1 |} что соответствует самому большому возможному числу$'.Для последовательностей с разным типом скобок надо определять свой порядокв зависимости от числа скобок, причем любая открывающаяся скобка должна быть меньше закрывающейся, например "$($"<"$[$"<"$)$"<"$]$".
''Примеры лексикографического порядка для $n$ и $k$, где $n$ - число открывающихся скобок, а $k$ - число видов скобок''
|id = def1
|definition =Числа Каталана {{---}} последовательность чисел, выражающих:
*количество неизоморфных не изоморфных упорядоченных бинарных деревьев с корнем и $n + 1$ листьями;*количество способов соединения $2n$ точек на окружности n непересекающимися не пересекающимися хордами;*количество разбиений выпуклого $(n + 2)$ - угольника на треугольники непересекающимися не пересекающимися диагоналями;
*количество правильных скобочных последовательностей имеющих $n$ открывающихся скобок.}}
Числа Каталана удовлетворяют следующему рекурентному рекуррентному соотношению:
$C_0 = 1$; {{---}} так как существует только одна скобочная последовательность с $0$ открывающихся скобок - пустая
$C_n = \sum_{i = 1}^{n - 1} C_i C_{n - 1 - i}$.
 Это соотношение легко получается из (*). Для этого надо перебрать все возможные последовательности $d_1S$ и $d_2S2$, являющиеся правильными скобочными последовательностями, такие, что $(d_1S1)d_2S2$ образуют новые правильные скобочные последовательности необходимой нам длины.
''Генерация следующей скобочной последовательности:''
Пусть нам известна строка $s$, представляющая собой правильную скобочную последовательность. Нам необходимо вывести следующую скобочную последовательность, а если ее нет, то - "No solution". Воспользуемся интерпретацией (**). Чтобы получить следующий битовый вектор следующую скобочную последовательность надо найти самый последний нулевой элемент, заменить его на единицу, а элементы следующие за ним сделать минимально возможными (все нули). Тоже самое и со скобочными последовательностями, только после замены нуля на единицу оставшиеся скобки надо расположить в минимальном порядке (в виде (***))минимальную:
function bool next(var s: string): boolean; var i, k, l:integer; begin k :pointer_close = 0; {счетчик для закрывающихся скобок} l :pointer_open = 0; {счетчик для закрывающихся скобок} for (i := length(s) downto 1 do {Начинаем перебирать скобки с конца} begin; i > 0; i--): if (s[i] == '(' then ): beginpointer_open++ inc if (lpointer_closed > pointer_open); if k > l then {встретив открывающуюся скобку, которую можно поменять на закрывающуюся, меняяем ее и выходим из цикла} break; end
else
inc(k); end;pointer_closed++ delete(s, length(s) - l pointer_open - k pointer_closed + 1, k pointer_closed + l); {удаляем все скобки включая открывающуюся} if (s = '' then): next := return false else begin s := s +')'; {записываем закрывающуюся скобку} for (j := 1 to ; j > l do {расставляем скобки в минимально возможном порядке}+ 1; j++): s := s + '('; for (j := 1 to k - 1 do; j > pointer_closed; j++): s := s + ')'; next := return true; end; end;
Если эта функция после выполнения выводит $true$ тогда надо напечатать полученную строку $s$, если $false$, то следует вывести "No solution".
Пусть нам известно число $n$. Надо вывести все правильные скобочные последовательности в лексикографическом порядке с $n$ открывающимися скобками:
procedure void (n: integer); var s: string; j: integer; t: boolean; begin s := ' '; {s присваиваем значение пустой строки} if (n == 0 then): writeln result(s) else begin for (j := 1 to ; j < n do {создаем начальную строку}+ 1; i++) s := s + '('; for (j := 1 to ; j < n do+ 1; i++) s := s + ')'; writeln result(s); t := next(s); while (t <> false do {выполняем до тех пор пока не будет получена последняя последовательность}) begin writeln result(s); t := next(s); end; end; end; return
Так же с помощью этого алгоритма можно получить скобочную последовательность по номеру и номер по скобочной последовательности, добавив сравнение с нужной последовательностью и счетчик. Но это далеко не самый оптимальный алгоритм для подобного типа задач и он не будет нормально работать для больших $n$.
Анонимный участник

Навигация