Можно ли подсчитать количество различных подстрок в строке в 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 соответствие между подстроками и путями через trie (по определению trie); и
- существует 1-1 соответствие между буквами в дереве и непустые пути, потому что:
- каждый отдельный непустой путь заканчивается в определенном месте после его последней буквы; и
- путь к позиции после каждой буквы уникален
примечание для людей, которые задаются вопросом, как можно построить дерево, содержащее O (N^2) символов в O (N) времени:
есть трюк, чтобы представление дерева суффиксов. Вместо хранения фактических строк в узлах дерева вы просто храните указатели в исходной строке, поэтому узел, содержащий "abb", не имеет" abb", он имеет (0,3) -- 2 целых числа на узел, независимо от длины строки в каждом узле, а дерево суффиксов имеет O(N) узлов.
построить массив LCP и вычесть его сумму из числа подстрок (n (n+1)/2).