Вступление
Предположим, вы и ваш друг играете в игру. Ваш друг думает о какой-то определенной последовательности n
битов, а ваша задача - определить последовательность, задав им вопросы. Тем не менее, единственный тип вопроса, который вам разрешено задавать, это «Какова самая длинная общая подпоследовательность вашей последовательности и S
», где S
- любая последовательность битов. Чем меньше вопросов вам нужно, тем лучше.
Задание
Ваша задача - написать программу или функцию, которая принимает в качестве входных данных положительное целое число n
и двоичную последовательность R
длины n
. Последовательность может быть массивом целых чисел, строкой или другим разумным типом по вашему выбору. Ваша программа должна вывести последовательность R
.
Ваша программа не имеет права доступа к последовательности R
напрямую. Только , что это разрешено сделать , R
это дать ему в качестве входных данных для функции len_lcs
наряду с другой двоичной последовательностью S
. Функция len_lcs(R, S)
возвращает длину самой длинной общей подпоследовательности R
и S
. Это означает самую длинную последовательность битов, которая встречается как (не обязательно непрерывная) подпоследовательность в обоих R
и S
. Входы len_lcs
которых могут быть разной длины. Программа должна вызывать эту функцию R
и другие последовательности некоторое количество раз, а затем восстанавливать последовательность R
на основе этой информации.
пример
Рассмотрим входы n = 4
и R = "1010"
. Во-первых, мы можем оценить len_lcs(R, "110")
, что дает 3
, так как "110"
это самая длинная общая подпоследовательность "1010"
и "110"
. Тогда мы знаем, что R
получается "110"
путем вставки одного бита в какую-то позицию. Далее мы могли бы попытаться len_lcs(R, "0110")
, который возвращает, 3
так как самые длинные общие подпоследовательности "110"
и "010"
, следовательно "0110"
, не верны. Затем мы пытаемся len_lcs(R, "1010")
, который возвращается 4
. Теперь мы знаем это R == "1010"
, поэтому мы можем вернуть эту последовательность как правильный вывод. Это потребовало 3 звонка len_lcs
.
Правила и оценки
В этом репозитории вы найдете файл, subsequence_data.txt
содержащий 100 случайных двоичных последовательностей длиной от 75 до 124. Они были сгенерированы путем трех случайных операций a
с a
плавающей запятой в диапазоне от 0 до 1, взяв их среднее значение как , а затем перевернув смещенное n
время монеты . Вы набираете среднее количество обращений кlen_lcs
этим последовательностям, при этом более низкий балл. Ваша заявка должна записать количество звонков. Ограничений по времени нет, за исключением того, что вы должны запустить свою программу в файле перед отправкой.
Ваше представление должно быть детерминированным. ГСЧ разрешены, но они должны использовать текущую дату 200116
(или ближайший эквивалент) в качестве случайного начального числа. Вам не разрешено оптимизировать свою работу в соответствии с этими конкретными тестовыми примерами. Если я подозреваю, что это происходит, я создам новую партию.
Это не кодовый гольф, поэтому рекомендуется писать читаемый код. У кода Розетты есть страница с самой длинной общей подпоследовательностью ; Вы можете использовать это для реализации len_lcs
на своем языке по вашему выбору.
lcs
вместо того, чтобы получить доступ к нейlen_lcs
.lcs(R, "01"*2*n)
возвращаетсяR
. ;) Но это может сработать, если коллlcs(R, S)
увеличит счетlen(S)
вместо 1, или что-то в этом роде ...Ответы:
Java,
99.0498.4697.66 lcs () вызовыКак это устроено
Exaple: Наша линия , которая должна быть реконструирована является
00101
. Сначала мы выясняем, сколько существует нулей, сравнивая (здесь сравнивая = вычисление lcs с исходной строкой) только строку с нулями00000
. Затем мы проходим через каждую позицию, флип0
к1
и проверить , если мы теперь имеем больше общую подстроку. Если да, примите и перейдите к следующей позиции, если нет, переверните текущую1
обратно на a0
и перейдите к следующей позиции:Оптимизации
Это всего лишь «наивная» реализация, возможно, было бы возможно найти более сложный алгоритм, проверяющий несколько позиций одновременно. Но я не уверен, что на самом деле это лучше один (например , на основе вычисления битов четности по аналогии с кодом Хэмминга), как вы всегда можете просто оценить длину от общей подстроки.
Для одной данной строки цифр этот алгоритм нуждается в точных
#ofDigitsUntilTheLastOccurenceOf1 + 1
проверках. (Вычтите одно, если последние цифры1
.)РЕДАКТИРОВАТЬ: Одна небольшая оптимизация: если мы только что проверили 2-ю последнюю цифру, и нам все еще нужно вставить
1
, мы точно знаем, что она должна быть в самой последней позиции, и можем пропустить соответствующую проверку.РЕДАКТИРОВАТЬ 2: Я только что заметил, что вы можете применить вышеупомянутую идею к последней
k
.Конечно, можно было бы добиться немного более низкого результата с помощью этой оптимизации, переупорядочив сначала все строки, потому что это может быть, что вы получите больше строк с единицами в самом конце, но это, очевидно, будет и оптимизация для текущего тестовые случаи, которые больше не смешно.
время выполнения
Верхний предел есть
O(#NumberOfBits)
.Полный код
Вот полный код:
источник
1
, что эквивалентно тому, что остались только нули.