Каковы хорошие тестовые примеры для алгоритмов поиска подстроки и тестирования напряжения?

Я пытаюсь оценить различные алгоритмы и реализации алгоритмов подстроки (ala strstr) и ищет некоторые хорошо продуманные строки иглы и стога сена, которые уложат худшую производительность и возможные ошибки в угловом корпусе. Полагаю, я мог бы самостоятельно их обработать, но я полагаю, что кто-то должен иметь хорошую коллекцию тестовых примеров, сидящих где-то...

Ответ 1

Некоторые мысли и частичный ответ на меня:

Наихудший случай для алгоритма грубой силы:

a^(n+1) b в (a^n b)^m

например. aaab в aabaabaabaabaabaabaab

Наихудший случай для SMOA:

Что-то вроде yxyxyxxyxyxyxx в (yxyxyxxyxyxyxy)^n. Требуется дальнейшая доработка. Я пытаюсь обеспечить, чтобы каждое продвижение составляло только половину длины частичного совпадения, и для вычисления максимального суффикса требуется максимальная сумма обратного отслеживания. Я уверен, что я на правильном пути, потому что этот тип случая - единственный способ, который я нашел до сих пор, чтобы моя реализация SMOA (асимптотически 6n+5) выполнялась медленнее, чем glibc Two-Way (что асимптотически 2n-m, но имеет умеренно болезненные служебные данные предварительной обработки).

Самый худший случай для чего-то подвижного хеша:

Любая последовательность байтов вызывает хеш-столкновения с хешем иглы. Для любого разумно быстрого хэша и заданной иглы должно быть легко построить стог сена, чей хеш сталкивается с хешей иглы в каждой точке. Однако, кажется, трудно одновременно создавать длинные частичные совпадения, которые являются единственным способом получить наихудшее поведение. Естественно, что при худшем случае игла должна иметь некоторую периодичность и способ эмуляции хэша путем настройки только конечных символов.

Наихудший случай для двухстороннего:

Кажется, очень короткая игла с нетривиальным разложением MS - что-то вроде bac - где стог сена содержит повторяющиеся ложные срабатывания в правой половине компонента иглы - что-то вроде dacdacdacdacdacdacdac. Единственный способ, которым этот алгоритм может быть медленным (за исключением того, что авторы glibc плохо его реализуют) заключается в том, что внешний цикл повторяется многократно и неоднократно подвергается этим накладным расходам (и делает значительную нагрузку на настройку).

Другие алгоритмы:

Мне действительно интересны только алгоритмы, которые O(1) в пространстве и имеют низкую нагрузку на предварительную обработку, поэтому я не рассматривал их наихудшие случаи. По крайней мере, Бойер-Мур (без модификаций сделать его O(n)) имеет нетривиальный худший случай, когда он становится O(nm).

Ответ 2

Не отвечает на ваш вопрос напрямую, но вы можете найти алгоритмы в книге - Алгоритмы по строкам, деревьям и последовательностям: информатика и вычислительная биология - интересны (имеется много новых алгоритмов поиска подстроки). Кроме того, это также хороший источник особых и сложных случаев.

Ответ 3

Процедура, которая может дать интересную статистику, хотя у меня нет времени на тестирование прямо сейчас:

Рандомизировать длину строки, затем рандомизируйте содержимое строки этой длины, затем рандомизируйте по смещению/длине подстроки (возможно, что-то не в строке), затем случайным образом clobber над подстрокой (возможно, совсем не), повторить.

Ответ 4

Вы можете генерировать строки контейнера (соответственно, содержащиеся тестовые значения) рекурсивно:

Начиная с пустой строки, сгенерируйте все строки, заданные дополнением строки, текущей в наборе, добавив символ из алфавита влево или вправо (оба).

Алфавит для создания строк контейнера выбран вами.

Вы проверяете 2 алфавита для содержащихся строк. Один из них представляет собой контейнерные строки, другой - его дополнение.