Несколько недель назад Lembik задал следующий вопрос:
Период
p
строкиw
- любое натуральное числоp
такое, чтоw[i]=w[i+p]
когда обе стороны этого уравнения определены. Обозначим черезper(w)
размер наименьшего периодаw
. Будем говорить, что строкаw
равна периодический iffper(w) <= |w|/2
.
Так что неофициально периодическая строка - это просто строка, которая состоит из другой строки, повторяемой хотя бы один раз. Единственное осложнение состоит в том, что в конце строки нам не требуется полная копия повторяющейся строки, если она повторяется во всей полноте хотя бы один раз.
Для примера рассмотрим строку x = abcab
. per(abcab) = 3
как x[1] = x[1+3] = a
, x[2]=x[2+3] = b
и не существует меньшего периода. Поэтому строка abcab
не является периодической. Однако строка ababa
является периодической как per(ababa) = 2
.
В качестве дополнительных примеров abcabca
, ababababa
и abcabcabc
также являются периодическими.
Для тех, кто любит регулярные выражения, этот определяет, является ли строка периодической или нет:
\b(\w*)(\w+\1)\2+\b
Задача состоит в том, чтобы найти все максимальные периодические подстроки в более длинной строке. Они иногда называют работает в литературе.
Подстрока
w[i,j]
ofw
- это максимальная периодическая подстрока (run), если она периодическая, и ниw[i-1] = w[i-1+p]
, ниw[j+1] = w[j+1-p]
. Неформально "прогон" не может содержаться в более крупном "пробеге", с тем же периодом.
Поскольку два прогона могут представлять одну и ту же строку символов, встречающихся в разных местах в общей строке, мы будем представлять пробеги через интервалы. Здесь приведенное выше определение повторяется с точки зрения интервалов.
Запуск (или максимальная периодическая подстрока) в строке
T
является интервалом[i...j]
сj>=i
, что
T[i...j]
- это периодическое слово с периодомp = per(T[i...j])
- Максимум. Формально ни
T[i-1] = T[i-1+p]
, ниT[j+1] = T[j+1-p]
. Неформально прогон не может содержаться в большем тираже с тем же периодом.
Обозначим через RUNS(T)
множество пробегов в строке T
.
Примеры прогонов
-
Четыре максимальные периодические подстроки (пробеги) в строке
T = atattatt
:T[4,5] = tt
,T[7,8] = tt
,T[1,4] = atat
,T[2,8] = tattatt
. -
Строка
T = aabaabaaaacaacac
содержит следующие 7 максимальных периодических подстрок (пробегов):T[1,2] = aa
,T[4,5] = aa
,T[7,10] = aaaa
,T[12,13] = aa
,T[13,16] = acac
,T[1,8] = aabaabaa
,T[9,15] = aacaaca
. -
Строка
T = atatbatatb
содержит следующие три пробега. Они есть:T[1, 4] = atat
,T[6, 9] = atat
иT[1, 10] = atatbatatb
.
Здесь я использую 1-индексацию.
Цель
Запишите код, чтобы для каждого целого числа n, начинающегося с 2, вы выводили наибольшее количество прогонов, содержащихся в любой двоичной строке длиной n
.
Пример optima
В следующем: n, optimum number of runs, example string
.
2 1 00
3 1 000
4 2 0011
5 2 00011
6 3 001001
7 4 0010011
8 5 00110011
9 5 000110011
10 6 0010011001
11 7 00100110011
12 8 001001100100
13 8 0001001100100
14 10 00100110010011
15 10 000100110010011
16 11 0010011001001100
17 12 00100101101001011
18 13 001001100100110011
19 14 0010011001001100100
Существует ли более быстрый способ найти оптимальное количество прогонов для увеличения значений
n
, чем наивный подход O (n ^ 2 2 ^ n)?