Дана строка1
(или ряд чисел, это не так важно) и дана строка2
, которая будет являться подпоследовательностью строки1
.
Как можно реализовать следующее: убрать какое-то минимальное количество элементов из строки1
, чтобы не получилось такой подпоследовательности?
Например для строки abcdefacb
и подпоследовательности acb
ответом будет abcdefac
. Подпоследовательностью, простым языком, можно назвать какие-то элементы, в какой-то строке или каком-то ряде, при удалении между ними элементов образуется подстрока или подряд, или подмассив (последовательность). По сути, то же, но элементы не должны обязательно быть подряд идущими.
Эта задача решается с помощью динамического программирования.
Сначала "на пальцах". Пусть у нас строка 2 состоит из 2 символов ab
. Тогда a
мы в строке 1 должны убирать сначала (сколько нужно) а символы b
с конца. При это последний убранный a
будет раньше чем первый убранный b
(очевидно). Можно уже начинать перебирать границу раздела, поддерживая число символов (за линейно).
Что делать, если строка длиннее. Для простоты понимания с конца. Пусть мы уже взяли предпоследний (N-1
) символ строки 2 и он перешёл в j
строки 1. Тогда мы должны удалить все последние (N
) символы строки 1. Заполнили массив F[N-1][j]
. Теперь пусть мы расставили N-2
символов. Используя идею из упрощения с 2 символами мы можем перебрать точку оптимальности (выбрать отрезок [j,k]
такой что число элементов равный N
на нём плюс F[N-1][k]
будет минимально). Так мы получили F[N-2][j]
. Повторять N раз.
При правильной реализации сложности будет квадратичная. Если не получается за квадрат - пишите за куб.
P.S. я надеюсь оптимальнее по времени это решать нет необходимости (это возможно).
Возможное решение, но нужно проверять на тестах:
Есть строка "21212122" и подстрока "121"
Для начала посчитаем и запомним позиции вхождения подстроки. У нас есть 2 вхождения на позиции 1 и 3(отсчет от 0). Длинна подстроки 3(121). Для каждого вхождения проверяем цепляем ли мы следующее вхождение.
1(вхождение) + 3(длинна подстроки) -1(отсчет от нуля) = 3
А 3 <= 3(следующие вхождение) Значит удаляем 3 символ. Иначе удаляем любой (допустим 1).
И так перебираем все вхождения.
Таким образом мы удалим минимальное количество символов из последовательности
Другой вариант перебором. Находим все вхождения. Идем циклом по вхождениям. Перебором удаляем по 1 символу, затем по 2, итд и проверяем как изменилась строка. В конце перебора удаляем наилучший вариант и идем к следующему вхождению
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Здравствуйте, использую в программе std::shared_ptr и программа начинает себя вести по странномуУ меня программа БД для школы и вот при добавлении...
В первой строке входных данных содержится число N (1 <= N <= 100000)Во второй строке задается последовательность из N больших латинских букв (буквы...
Почему в следующем коде std::swap не рассматривается в качестве кандидата при вызове swap и приходится писать его полностью с пространством имён?...