Есть небольшая изящная теорема о таких строках.
Строка состоит из одного и того же шаблона, повторяемого несколько раз, если и только если строка является нетривиальным вращением самой себя.
Здесь вращение означает удаление некоторого количества символов с начала строки и перемещение их назад.Например, строку hello
можно повернуть для формирования любой из следующих строк:
hello (the trivial rotation)
elloh
llohe
lohel
ohell
Чтобы понять, почему это работает, сначала предположим, что строка состоит из k повторяющихся копий строки w.Затем, удалив первую копию повторяющегося образца (w) с начала строки и прикрепив ее к задней части, вы получите ту же строку.Обратное направление немного сложнее доказать, но идея в том, что если вы поверните строку и вернетесь к тому, с чего начали, вы можете несколько раз применить это вращение, чтобы разбить строку на несколько копий одного и того же шаблона (этот шаблон являетсяСтрока, которую нужно было переместить в конец, чтобы выполнить вращение).
Теперь вопрос состоит в том, как проверить, так ли это.Для этого есть еще одна красивая теорема, которую мы можем использовать:
Если x и y - строки одинаковой длины, то x является вращением y тогда и только тогда, когда x является подстрокой yy.
В качестве примера мы можем видеть, что lohel
- это вращение hello
следующим образом:
hellohello
^^^^^
В нашем случае мы знаем, что каждая строка x будет всегдабыть подстрокой xx (она появится дважды, один раз в каждой копии x).Поэтому в основном нам просто нужно проверить, является ли наша строка x подстрокой xx, не позволяя ей совпадать с первым или наполовину символом.Вот одна строчка для этого:
function check(str) {
return (str + str).indexOf(str, 1) !== str.length;
}
Если предположить, что indexOf
реализован с использованием алгоритма быстрого сопоставления строк, он будет выполняться за время O (n), где n - длина входной строки.
Надеюсь, это поможет!