Предположим, нам дан набор из строк, S 1 , … , S n . Я хотел бы знать, является ли какая-либо из этих строк подстрокой любой другой строки в коллекции. Другими словами, я хотел бы алгоритм для следующей задачи:
Ввод:
Вывод: такой, что S i является подстрокой S j и i ≠ j , или None, если таких i , j не существует
Есть ли эффективный алгоритм для этого?
Если мы заменим «подстроку» на «префикс», то получится эффективный алгоритм (отсортируйте строки, затем выполните линейное сканирование для сравнения соседних строк; сортировка обеспечит смежность подстрок). Но кажется более сложным проверить, является ли какая-либо строка подстрокой какой-либо другой строки. Наивным алгоритмом является итерация по всем парам , но для этого требуется subst ( n 2 ) тестов подстрок. Есть ли более эффективный алгоритм?
Я думаю, мы могли бы назвать это "тестирование подстрок всех пар" или что-то в этом роде.
Моя конечная цель - обрезать коллекцию, чтобы ни одна строка не являлась подстрокой какой-либо другой, удаляя каждую из подстрок чего-то еще в коллекции.
Ответы:
Вы можете построить дерево суффиксов за линейное время и проверить, есть ли внутренний узел, соответствующий полной строке (постоянное время на узел).
Используя алгоритм Укконена , это можно сделать за линейное время; линейный в сумме всех длин строк.
Это занимает время, линейное по размеру дерева, которое само по себе является линейным по входному размеру.
Это снова занимает линейное время.
Отдельные терминальные маркеры на самом деле не нужны; одного, используемого для завершения всех строк, вполне достаточно, если вы разрешаете использовать несколько меток на листе.
источник