Блог пользователя Borisov

Автор Borisov, 10 лет назад, По-русски

Всем привет, пытаюсь решить тут вот эту задачу

Код написал, как смог)

Как я понял там можно использовать алгоритм lcs, но я с ним не сталкивался пока...

Хотелось бы, чтобы кто-нибудь взглянул на мой код и сказал какой косяк именно в моей реализации...

Заранее большое спасибо!

  • Проголосовать: нравится
  • -15
  • Проголосовать: не нравится

»
10 лет назад, # |
  Проголосовать: нравится +1 Проголосовать: не нравится

Мне кажется, это даже не задача на строки на самом деле, т.к. там речь о подпоследовательности, а не подстроке. Лично я делаю ставку на какую-нибудь жадность. Типа возьмём лексикографически наибольший символ из тех, что мы встречаем в обеих строках, потом наибольший из тех таких, которые в обеих строках справа от взятого и т.д.

Осталось только грамотно реализовать.

  • »
    »
    10 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    Мне кажется можно даже не искать этот минимум, а идти от "z" до "a" и брать символы, пока это возможно (они есть в обеих строках, точнее в той правой части, до которой мы отсекли) Должно за O(n) зайти.

    • »
      »
      »
      10 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится

      Ну, можно и так. Это уже тонкости реализации, основная идея та же...

    • »
      »
      »
      10 лет назад, # ^ |
      Rev. 3   Проголосовать: нравится -14 Проголосовать: не нравится

      Вам обоим все кажется да кажется, перекреститесь уже :).

      Задача совсем тупая. Найдем жадно с помощью стека лексикографически максимальные подпоследовательности для обеих строк (назовем их X' и Y'). Далее найдем наибольшую общую подпоследовательность X' и Y' (т.к. X' и Y' являются невозрастающими, это делается просто двумя указателями).

      UPD. Я с решением наврал. На тесте "aaab aaa" получится пустая строка.

  • »
    »
    10 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    Примерно так я и рассуждал, но не понятно, как нормально реализовать это желательно за O(n).

    Алгоритм здесь простой, найти подпоследовательность для 2-ух исходных строк, затем каждый раз искать лексикографически больший символ отсекая его и все что слева от него, и искать в оставшейся правой части до тех пор пока есть из чего выбирать.

    У меня проблема, как это все закодить...

    Как я понимаю, для нахождения общей подпоследовательности здесь надо использовать что-то быстрее квадрата, что я не могу сообразить и реализовать...

    Вот поэтому я создал этот пост.

    P.S — как я понял по голосам серых очень любят на CF.

    • »
      »
      »
      10 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится

      Берем символ "z", смотрим сколько раз он встречается в первой строке и сколько во второй(на том правом куске строки, который остался), после этого берем минимум из эти чисел и столько раз пишем "z", далее делаем то же самое с "y", потом "x" и так до "a" по алфавиту.

      • »
        »
        »
        »
        10 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится

        И это неправильно. Прежде чем "делать то же самое с 'y'", нужно удалить из обеих строк все символы от начала до k-ой по счета буквы 'z', где k — минимум среди количества букв 'z' в первой и во второй строках.

        • »
          »
          »
          »
          »
          10 лет назад, # ^ |
            Проголосовать: нравится 0 Проголосовать: не нравится

          Да, вы правы. Я пытался это сказать теми словами в скобочках, но когда начал кодить понял, что всё немного сложнее.

    • »
      »
      »
      10 лет назад, # ^ |
      Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

      Записываем для каждого символа позиции вхождений в строки. Сортируем. Перебираем символы с z до a. Берём в ответ минимум из числа подходящих вхождений данного символа в первой и второй строках. Находить можно бин. поиском.

      UPD: а можно просто pop_front'ом удалять лишнее и будет линейно.

»
10 лет назад, # |
  Проголосовать: нравится +1 Проголосовать: не нравится

Скорее всего, ваш код не уложится по времени. Писать квадрат при ограничениях в 10^5 не самая хорошая идея.