Дерево префиксов / суффиксов - это, на мой взгляд, стандартное, лучшее и наиболее осторожное решение для такого рода вещей.Вы не можете ошибиться с ними.
Но вот другая идея, которая прибегает к фильтрам Блума .Вы, вероятно, знаете, что это такое, но на всякий случай (и для других людей, читающих этот ответ): Фильтры Блума - это очень маленькие, очень компактные битовые векторы, которые приближают включение набора.Если у вас есть набор S и фильтр Блума для этого набора B (S), то
x ∈ S ⇒ x ∈ B(S)
, но ответная реакция ложна.Это то, что является вероятностным в структуре: существует ( количественная оценка ) вероятность того, что фильтр Блума вернет ложное срабатывание.Но приблизительное включение с помощью фильтра Блума дико быстрее, чем его тестирование на множестве.
( Простой случай использования : во многих приложениях БлумФильтр используется, ну, как фильтр . Проверка кэша стоит дорого, потому что вам нужно получить доступ к жесткому диску, поэтому такие программы, как Squid, сначала проверят небольшой фильтр Блума в памяти, и если фильтр Блумавозвращает положительный результат, затем Squid проверит кеш. Если он был ложно положительным, то это нормально, потому что Squid обнаружит это при фактическом посещении кеша - но преимущество в том, что фильтр Bloom избавит Squid отчтобы проверить кэш для большого количества запросов, где он был бы бесполезен.)
Фильтры Блума с некоторым успехом использовались при поиске строк.Вот эскиз (я могу вспомнить некоторые детали неправильно) этого приложения.Текстовый файл представляет собой последовательность из N строк.Вы ищете слово, состоящее из M букв (и ни одно слово не может быть разбито на две строки).Фаза предварительной обработки создаст ОДИН фильтр Блума для каждой строки, добавив каждую подпоследовательность строки в фильтр Блума;например, для этой строки
Touching this dreaded sight, twice seene of vs,
И соответствующий фильтр Блума будет создан с "T", "To", "Tou" ... "o", "ou", ... "vs, "," s "," s, ",", ".(Возможно, эта часть неверна. Или, возможно, вы захотите оптимизировать.)
Затем при поиске подслов размера M просто сделайте одну очень быструю проверку для каждого из фильтров Блума и при наличиинажмите, внимательно изучите линию, например, с помощью алгоритма KMP.На практике, если вы хорошо настроите свои фильтры Bloom, компромисс будет замечательным.Поиск невероятно быстр, потому что вы удаляете все бесполезные строки.
Я полагаю, что из этой концепции вы могли бы найти полезную схему для вашей ситуации.Прямо сейчас я вижу два очевидных приспособления:
либо разрезать ваш набор данных во множество блоков размера K (каждый со своим фильтром Блума, как строки в предыдущем примере);
или использовать своего рода дихотомию, где вы разбиваете набор на два подмножества, каждое с фильтром Блума, затем каждое подмножество делится на два поднабора со своим собственным фильтром Блума и т. Д. (если вы собираетесь добавить все подстроки, как предложено в описанном мною методе, эта вторая идея будет несколько непомерной - за исключением того, что вам не нужно добавлять все подстроки, только подстроки размером от 1 до 10).
Обе идеи могут быть изобретательно объединены для создания многослойных схем.