fregimus: (q)
[personal profile] fregimus
У меня возникла комбинаторная задачка со стековой машиной, которую было бы интересно проанализировать.

Представьте себе игру с перекладыванием карточек, целью которой является переставить карточки с буквами из исходного порядка в заданный. На каждой карточке написана или буква алфавита, или стрелка ↑. Правила перестановки букв таковы. Первоначально карточки с буквами и стрелкой выложены в ряд и берутся по одной слева направо. Если на карточке буква, то карточка кладется в стопку (если стопка пуста, то карточка будет в ней единственной, а если там уже есть карточки, то очередная карточка кладется поверх предыдущих). Если же на карточке стрелка, то эта карточка выбрасывается, а верхняя карточка из стопки выкладывается в отдельную строку для результата. Рассмотрим пример. Пусть задана последовательность карточек

О Р ↑ ↑ К ↑

Берем карточки слева направо по одной. Карточка О кладется в стопку, Р поверх нее. Затем первая стрелка велит выложить верхнюю карточку Р на выход, а вторая выкладывает (теперь верхнюю) О. Затем К кладется в стопку и следом, по команде последней стрелки, выкладывается на выход за первыми двумя. В результате получаем на выходе

Р О К

Вопрос задачи состоит в следующем. Пусть нам даны исходная строка (в нашем примере это ОРК) и предположительная выходная (РОК). Можно ли так разложить карточки-команды со стрелкой между буквами исходной строки, чтобы на выходе получилась заданная? Буквы в строке не обязательно все различные, например, А Н А Н А С — допустимая строка.

Можете легко проверить, что из строки А Б В можно получить только 5 из 6 возможных перестановок, а перестановку В А Б получить невозможно.

А ↑ Б ↑ В ↑ → А Б В
А ↑ Б В ↑ ↑ → А В Б
А Б ↑ ↑ В ↑ → Б А В
А Б ↑ В ↑ ↑ → Б В А
А Б В ↑ ↑ ↑ → В Б А

Предпочтительно конструктивное решение (т. е. правило расстановки), и, конечно, самое простое. Существует очевидное решение «в лоб»: будем расставлять n стрелок, где n длина строки, в любом возможном порядке, и проверять, получится ли на выходе искомая строка. Но нам придется перебрать n! возможных комбинаций — громадное число даже для 10 букв, так что такое решение не годится. Есть очень простое линейное в n решение для строки с различающимися буквами, но оно не работает, если разрешить повторы одинаковых букв в строке. А дальше ваш ход.

Доб. Наврал я с линейным решением — нашел контрпример.
Tags:

(no subject)

2011-10-29 15:21 (UTC)
Posted by [identity profile] fat-crocodile.livejournal.com
И всё-таки, за линейный алгоритм для случая без повторов. Я предлагаю такой:

начало:
- пустой стек
- индекс в строке входа на начале
- индекс в строке выхода на начале

шаг алгоритма:
- проверить текущий элемент строки выхода
- если он совпадает с верхушкой стека
---- поставить в строке входа стрелку в текущей позиции
---- выкинуть верхний элемент из стека
- иначе перемешаемся по строке входа вперёд и добавляем в стек элементы, пока не найдём искомый, ставим после него стрелочку

Если дошли до конца строки, а в стеке что-то не то -- значит не судьба.
Я не вижу, где тут может вкрасться нелинейность. Как объяснить это не ссылаясь на моё хорошее зрение:

- на каждом шаге мы либо снимаем верхний элемент стека -- O(1)
- либо движемся вперёд O(n)
- но суммарных движений вперёд не может быть больше чем n

значит в сумме это что-то типа O(2n) -- линейное.

Profile

fregimus: (Default)
fregimus

March 2014

S M T W T F S
       1
2 3456 78
910 1112 131415
16171819202122
23242526272829
3031     

Most Popular Tags

Page generated 2025-12-24 13:25

Expand Cut Tags

No cut tags