Почему реализованная в С++ string::substr() не использует алгоритм KMP (и не работает за O(N + M)) и работает за O(N * M)?
Я предполагаю, что вы имеете в виду find()
, а не substr()
, который не нуждается в поиске и должен выполняться за линейное время (и только потому, что он должен копировать результат в новую строку).
Стандарт C++ не определяет деталей реализации, а лишь в некоторых случаях указывает требования к сложности. Единственные требования сложности к операциям std::string
заключаются в том, что size()
, max_size()
, operator[]
, swap()
, c_str()
и data()
все являются постоянным временем. Сложность всего остального зависит от выбора, сделанного тем, кто реализовал библиотеку, которую вы используете.
Наиболее вероятная причина выбора простого поиска, а не чего-то вроде KMP, заключается в том, чтобы избежать необходимости в дополнительном хранилище. Если искомая строка не очень длинная и строка для поиска не содержит много частичных совпадений, время, необходимое для выделения и освобождения, вероятно, будет намного больше, чем стоимость дополнительной сложности.
Это исправлено в c++0x?
Нет, C++11 не добавляет никаких требований к сложности std::string
и уж точно не добавляет каких-либо обязательных деталей реализации.
Если сложность текущей подстроки не O(N * M), что это?
Это наихудшая сложность, когда искомая строка содержит много длинных частичных совпадений. Если символы имеют достаточно равномерное распределение, то средняя сложность будет ближе к O(N)
. Таким образом, выбрав алгоритм с лучшей сложностью для наихудшего случая, вы вполне можете сделать более типичные случаи намного медленнее.
person
Mike Seymour
schedule
15.01.2012
string::find
, см. мой пост: stackoverflow.com/questions/19506571/ - person Peter Lee   schedule 25.10.2013(std::string(n-1,'a')+"b"+std::string(n,'a')).find(std::string(n,'a'))
равно O(n^2) или хуже. Например. для n = 1 миллион на моем компьютере это занимает 21 секунду, но должно быть мгновенным (возможно, несколько миллисекунд). - person Don Hatch   schedule 12.04.2020