Можно ли посчитать количество различных подстрок в строке в O(n)?
Учитывая строку s
длины n
Можно ли посчитать количество различных подстрок в s
в O(N)?
пример
Входные данные: abb
Выход: 5
('abb', 'ab', 'bb', 'a', 'b'
)
Я провел некоторые исследования, но я не могу найти алгоритм, который решает эту проблему таким эффективным способом. Я знаю, что O(n^2) подход возможен, но есть ли более эффективный алгоритм?
Мне не нужно получать каждую из подстрок, просто общее количество отдельных (в случае, если это имеет значение).
2 ответа
Вы можете использовать алгоритм Укконена для построения дерева суффиксов за линейное время:
https://en.wikipedia.org/wiki/Ukkonen%27s_algorithm
Количество подстрок s - это количество префиксов строк в дереве, которое вы можете вычислить просто за линейное время. Это просто общее количество символов во всех узлах.
Например, ваш пример создает дерево суффиксов, например:
/\
b a
| b
b b
5 символов в дереве, поэтому 5 подстрок. Каждая уникальная строка представляет собой путь от корневого окончания, заканчивающегося другой буквой: abb, ab, a, bb, b. Таким образом, количество строк - это количество букв в дереве.
Точнее:
- Каждая подстрока является префиксом некоторого суффикса строки;
- Все суффиксы в три;
- Таким образом, существует соответствие 1-1 между подстроками и путями через три (по определению три); а также
- Существует соответствие 1-1 между буквами в дереве и непустыми путями, потому что:
- каждый отдельный непустой путь заканчивается в отдельной позиции после последней буквы; а также
- путь к позиции, следующей за каждой буквой, уникален
ПРИМЕЧАНИЕ для людей, которые задаются вопросом, как можно построить дерево, содержащее O(N^2) символов за O(N):
Есть хитрость в представлении дерева суффиксов. Вместо того, чтобы хранить фактические строки в узлах дерева, вы просто сохраняете указатели в оригинальной строке, поэтому узел, содержащий "abb", не имеет "abb", он имеет (0,3) - 2 целых числа в узел, независимо от длины строки в каждом узле, а дерево суффиксов имеет O(N) узлов.
Построить массив LCP и вычесть его сумму из числа подстрок (n(n+1)/2).