Обчисліть прогони рядка


11

Розглянемо наступні визначення, взяті з Кількість прогонів у рядку В. Райттера. Зауважте, що слово, рядок та підрядка - це приблизно синоніми.

Запуск у рядку - це нерозширюваний (з однаковим мінімальним періодом) періодичний сегмент у рядку.

Період p слова w - це будь-яке додатне ціле p, таке, що w [i] = w [i + p], коли визначаються обидві сторони цього рівняння. Нехай per (w) позначає розмір найменшого періоду w. Ми говоримо, що слово w - періодичне iff per (w) <= | w | / 2.

Для прикладу розглянемо рядок x = abcab. per(abcab) = 3як x[1] = x[1+3] = a, x[2]=x[2+3] = bі менший період не існує. Тому рядок не abcabє періодичним. Однак рядок ababє періодичним відповідно до (abab) = 2.

Пробіг (або максимальна періодичність) у рядку w - це інтервал [i ... j] з j> = i, такий, що

  • w [i ... j] - періодичне слово з періодом p = per (w [i ... j])
  • Це максимально. Формально ні w [i-1] = w [i-1 + p], ні w [j + 1] = w [j + 1-p]. Неофіційно запуск не може міститись у більшому циклі з тим самим періодом.

Позначимо через RUNS (w) набір прогонів w.

Приклади

Чотири прогони atattattстановлять [4,5] = tt, [7,8] = tt, [1,4] = atat, [2,8] = таттатт.

Рядок aabaabaaaacaacacмістить наступні 7 запусків:

[1,2] = aa, [4,5] = aa, [7,10] = aaaa, [12,13] = aa, [13,16] = acac, [1,8] = aabaabaa, [9 , 15] = акаака.

Вашим результатом повинен бути список запусків. Кожен запуск повинен визначати інтервал, який він представляє, але не потрібно виводити саму підрядку. Точне форматування може бути будь-яким зручним для вас.

У прикладах використовується 1-індексація, але ви можете використовувати натомість 0-індексацію, якщо це зручніше.

ЗАВДАННЯ

Напишіть код, який задав рядок w, виведіть RUNS (w).

Мови та введення

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


4
Хороший виклик, але чи є вагомі причини відміняти функції за замовчуванням та забороняти функції?
Мартін Ендер

@MartinEnder Це просто мої переваги. Людям стає простіше просто скопіювати та вставити код та спробувати його самостійно, що в свою чергу робить відповіді більш цікавими для більшості людей.

4
Але це також спричиняє багато накладних кодів, що робить конкуренцію несправедливою для мов з багатослівним синтаксисом. Наприклад, я б не займався гольфом на Яві, якби мені доводилося писати class A{public static ...}кожен раз, коли я хотів гольф-код
Bassdrop Cumberwubwubwub

@BassdropCumberwubwubwub Я можу бачити, що є плюси і мінуси. Я випадково зважую плюси сильніше. Я думаю, що найцікавіше в будь-якому випадку порівнювати довжину відповідей на гольф подібними мовами, а не порівнювати, наприклад, APL з Python.

"пробіг є максимальним, якщо він не міститься повністю в будь-якому великому циклі", але у вашому першому прикладі [7,8] повністю міститься в межах [2,8]. Або ви суворо говорите про запуски, які повторюють ту саму підрядку?
aditsu кинути, тому що SE - EVIL

Відповіді:


2

Pyth, 38 байт

{smm,hk+ekdfgaFTdcx1xM.ttB+0qVQ>QdZ2Sl

  m                                 SlQ   map for d in [1, …, len(input)]:
                            qVQ>Qd          pairwise equality of input[:-d] and input[d:]
                        tB+0                duplicate this list, prepending 0 to one copy
                      .t          Z         transpose, padding with 0
                    xM                      pairwise xor
                  x1                        find all occurrences of 1
                 c                 2        chop into groups of 2
           f                                filter for groups T such that:
             aFT                              the absolute difference between its elements
            g   d                             is greater than or equal to d
   m                                        map for groups k:
     hk                                       first element
    ,  +ekd                                   pair with the last element plus d
 s                                        concatenate
}                                         deduplicate

Тестовий набір


Я отримую "[[3, 5], [6, 8], [0, 4], [1, 8]]" від "atattatt". Чи [3,5] представляє "tt"? Було б чудово, якби ви могли пояснити використаний алгоритм на високому рівні.

@Lembik Так, [i, j]являє собою зріз починаючи між (0-індексованих) символів i-1і iі закінчуючи між символами j-1і j. Це стандартна конвенція в Pyth і найбільш здорових мовах, як це має бути (див. Тут і тут ).
Anders Kaseorg

Чудово. Чи можливо описати своє рішення інтуїтивно? На жаль, я не можу його змінити з опису коду.

1
@ Лембік Припустимо, ми шукаємо пробіжки періоду d. Ми знаходимо всі місця, де символ i відповідає символу i + d. Потім ми знаходимо прогони принаймні d поспіль таких локацій. Повторіть для всіх d. Нам потрібно дедублікувати наприкінці, оскільки реальний період міг би бути лише дільником d.
Anders Kaseorg

1

CJam, 66

q:A,2m*{~A>_@)_@<2*@@2*<=},{_2$-2>2,.+={+}&}*]{[_1=\)\0=2*)+]}%_&p

Спробуйте в Інтернеті

Коротке пояснення:

Алгоритм працює в 4 етапи (перші 3 з них відповідають трьом основним блокам, які ви можете спостерігати):

  1. Знайдіть усі пари [індекс довжини], які відповідають дублюваній підрядці (наприклад, аба аба ааакаак); це частини пробіжок.
  2. З'єднайте пари, що є частиною одного прогону, тобто послідовних індексів та однакової тривалості / періоду.
  3. Побудуйте фактичні прогони, взявши мінімальний індекс та максимальний індекс + 2 * довжина - 1.
  4. Наприкінці видаліть дублювані прогони (це той самий інтервал, отриманий за інший період)

Я хотів би більше пограти в гольф, тому це все може змінитися.


Дякую за це. Чи можете ви пояснити алгоритм, який ви також використали?

1
@Lembik ок, оновлено
aditsu кине, тому що SE - EVIL
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.