Почему jdk String.indexof() не использует KMP?

Я прочитал исходный код java.lang.String, и я был удивлен, узнав, что String.indexof() не использует алгоритм KMP? Как мы знаем, KMP более эффективен, поэтому почему он не используется в String.indexof()?

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

Итак, вот мои вопросы:

  • Почему мы не используем KMP в методе String.indexof()?
  • Почему KMP не является хорошим выбором с большими строками?

Ответ 1

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

Для (предположительно) общих случаев использования в относительно коротких строках это может фактически оказаться медленнее, чем примитивная реализация.

Это связано с тем фактом, что для действительно огромных наборов данных вы, вероятно, будете использовать более специализированные структуры данных, чем простой String означает, что затраты на увеличенную реализацию (и, возможно, время выполнения) не стоит инвестировать.

Обратите внимание, что это может измениться в будущих версиях Java, поскольку фактический алгоритм не указан.

Ответ 2

KMP и несколько других асимптотически эффективных методов поиска строк, таких как Boyer-Moore и Boyer-Moore-Horspool, требуют дополнительной памяти - в случае памяти KMP, O (m), где m - размер подстроки, Хотя это часто бывает приемлемым, разработчики библиотеки должны делать компромиссы, чтобы их код хорошо проходил во многих ситуациях. Вероятно, основная причина заключается в том, что из-за как предварительной обработки, требуемой KMP, так и более сложной внутренней петли на этапе поиска, замедление постоянного фактора может сделать его в несколько раз медленнее, чем наивный поиск подстроки O (mn) во многих распространенных случаях ( например, поиск подстроки в 10 символов в длинной строке). Кроме того, кто-то, кто ищет большую подстроку, может быть озадачен, обнаружив, что библиотека времени выполнения исчерпала память, пытаясь выделить большой буфер памяти для таблицы функций резервного копирования KMP.

Возможно, лучший вопрос - почему алгоритмы O (m + n) -time, O (1) -пространства, такие как Двусторонний алгоритм до сих пор не был принят библиотеками времени исполнения основного языка. Опять же, ответ, вероятно, будет замедлением постоянного фактора в обычных случаях. Тем не менее, по крайней мере в одной реализации библиотеки времени выполнения C, для использования этого алгоритма была обновлена ​​соответствующая функция strstr() .

Кто-то вокруг меня сказал мне, что для короткой струны KMP достаточно хорошо, но если вам нужна производительность, и вы намерены использовать ее с большой строкой то это не лучший выбор.

Ну, это точно назад от моего понимания, а именно, что наивный поиск подстроки O (mn) достаточно хорош (и, вероятно, лучший) для коротких строк, но в конечном итоге потеряет асимптотически быстрее O (m + n) алгоритмы, подобные KMP, поскольку строки становятся длиннее.