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

Автор Gerald, 15 лет назад, По-русски
На одной из тренировок школьников на NEERC в этом году, была одна интересная строковая задача. Вот её приблизительное условие:
Строка называется хорошей, если какой либо её префикс ненулевой длины и отличный от всей строки совпадает с её суффиксом. Дана строка длиной до 105 символов, нужно для каждого её циклического сдвига определить является он хорошим или нет.

Условие в оригинале и авторское решение по задаче можно найти где-то-тут. Оригинальное название задачи "Заклинание Границы".

В авторском решении, что-то весьма хитрое с z-функцией и разделяй-и-властвуй, кажется, я не очень понял. Предлагаю пообсуждать решение здесь :). 


P.S. Некто e-maxx, говорил, что, вроде бы, подобная задача была когда то в Петрозаводске на Станкевич контесте. И что у нее есть решение как z-функцией, так и суффиксным деревом. 
  • Проголосовать: нравится
  • +6
  • Проголосовать: не нравится

15 лет назад, скрыть # |
 
Проголосовать: нравится -8 Проголосовать: не нравится

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

Если не проходит по времени, увеличиваем таймлимит :о)

15 лет назад, скрыть # |
Rev. 5  
Проголосовать: нравится +3 Проголосовать: не нравится
UPD: это неверно. См. далее верное решение.
  • 15 лет назад, скрыть # ^ |
     
    Проголосовать: нравится 0 Проголосовать: не нравится
    Для каждого суффикса t длины большей n (он отвечает какому-то циклическому сдвигу s) определим, какая вершина дерева соответствует суффиксу tR (то бишь префиксу t) такому, что их пересечение образует в точности циклический сдвиг - т.е. искомый префикс t кончается в позиции, отстоящей на n вперёд от начала рассматриваемого суффикса t. Вроде бы это можно сделать за O(N).
    Я что-то не понимаю, как это за O(N) сделать.
    • 15 лет назад, скрыть # ^ |
       
      Проголосовать: нравится 0 Проголосовать: не нравится
      Ну как же. Если у нас есть суффикс t[i..], то мы знаем, в каком символе должен начинаться парный ему — это tR[(n - i)..], ибо циклический сдвиг — это t[i..(i + n - 1)]. В процессе построения дерева tR, как только мы достроили ветку для этого парного суффикса n - i, надо просто в каком-то заведенном массивчике для i-го суффикса t прописать ссылку на эту вершину дерева.
  • 15 лет назад, скрыть # ^ |
    Rev. 3  
    Проголосовать: нравится +8 Проголосовать: не нравится
    А в tR же суффикс будет отвечать не префиксу исходной строки, а перевернутому префиксу. Т.е. к примеру строка abab - не будет хорошей, т.к. ab != ba, а она хорошая.

    Или я не правильно понял идею?
15 лет назад, скрыть # |
Rev. 3  
Проголосовать: нравится 0 Проголосовать: не нравится

Думается всетаки можно таким методом решить.

Научимся решать: http://olympiads.ru/zaoch/2009/problems/k.shtml .

Я в свое время решал с помощью KMP. Собственно, текст в котором ищем text = s + s, искомый образец patern = s. n = strlen(s). Как обычно построим префикс функцию и начнем искать образец в тексте. Начиная с символа n-1 (индексация с 0) при поиске образца в тексте обращаем внимание на следующий факт.

Если после некоторой итерации указатель на символ в образце равен n, то в случае с задачей поиска строки в подстроке можно говорить о том, что найдено вхождение образца в текст. В нашей же задаче значение указателя -- это и будет наибольший префикс, который является суффиксом. Если p = n, то возьмем значение префикс функции от s.

  • 15 лет назад, скрыть # ^ |
     
    Проголосовать: нравится 0 Проголосовать: не нравится
    Понимаете так делать нельзя. Так вы найдете наибольший суффикс который равен префиксу нулевого циклического сдвига строки. То есть у вас суффикс меняется всё время, а префикс нет.

    P.S. Задача уже решена, сверху Skiminok написал отличное решение с помощью нахождение тандемных повторов.
15 лет назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится
Эта задача решается суфф. массивом. + rmq + dsu. придумал еще на контесте, но не успел написать.

Посмотрим на циклический сдвиг i. Когда он хороший? когда  .  Отлично. Построим суффмассив по циклическим сдвигам строки s. Посчитаем lcp.

Проверим условие для всех j, расположенных в суфмассиве раньше чем i. Симметрично сделаем для остальных.

Будем идти по массиву с начала в конец. На i-ом шаге ответим для i-го лексикографически цикл. сдвига. Очевидно что проверка - запрос к дереву отрезков для написанной выше функции. Осталось эту функцию пересчитать. Утверждается что в любой момент все строки можно разбить на множества с одинаковым lcp, причем эти множества - отрезки в суффмассиве. Честно объедением отрезки которые теперь имеют одинаковое lcp. Не сложно что это несколько отрезков ближних к текущей позиции. Причем таких объединений всего O(N). Кадое делается деревом отрезков за log. Чтобы просто понимать на каких отрезках делать объединение поможет dsu. Думаю можно и без него. Итого суммарно O(NlogN).

Думаю что написал довольно криво, вопросы приветствуются.