我阅读了java.lang.String
的源代码,我惊讶地发现String.indexof()
没有使用the Knuth–Morris–Pratt algorithm?众所周知,KMP更有效。那么为什么不在String.indexOf()
中使用它?
我周围的人告诉我,对于短串KMP是足够好的,但是如果你需要性能而你打算使用大字符串那么这不是一个好的选择。但他并没有告诉我细节。
所以,这是我的问题:
String.indexOf()
使用KMP?答案 0 :(得分:19)
KMP具有更好的最坏情况性能,但实际上需要一些前期计算(以生成偏移表)。它也需要初始内存分配,这也会影响性能。
对于(大概)在相对较短的字符串中搜索的常见用例,这实际上可能比原始实现更慢。
这与这样一个事实捆绑在一起:对于真正庞大的数据集,您可能会使用比简单String
更专业的数据结构,这意味着增加的实现(以及可能的运行时)成本不值得投资。
请注意,此可能会在未来的Java版本中进行更改,因为未指定实际算法。
答案 1 :(得分:9)
KMP和其他几个渐近有效的字符串搜索方法,如Boyer-Moore和Boyer-Moore-Horspool需要额外的内存 - 在KMP,O(m)内存的情况下,其中m是要搜索的子字符串的大小。虽然这通常是可以接受的,但是图书馆设计者必须进行权衡,以便他们的代码在许多不同的情况下表现得非常好。可能主要原因是由于KMP所需的预处理以及搜索阶段中更复杂的内循环,在许多常见情况下,常数因子减速可能会比原始O(mn)子串搜索慢几倍(例如,在长字符串中搜索<10个字符的子字符串)。此外,在尝试为KMP回退函数表分配大内存缓冲区时,搜索大型子字符串的人可能会感到困惑,无法找到内存不足的运行时库。
或许更好的问题是为什么 O(m + n)-time,O(1)-space 算法(如Two-Way Algorithm尚未被主流语言运行时库采用。同样,答案可能是常见情况下的常数因素减缓。然而,在至少一个C运行时库实现中,相应的strstr()
函数has been updated to use this algorithm。
我周围的人告诉我,短串KMP足够好了, 但是如果你需要性能而你打算使用大字符串 那不是一个好的选择。
嗯,这完全是我的理解后退,这就是天真的O(mn)子串搜索对于短字符串来说已经足够好(并且可能是最好的),但最终会失去渐近更快的O(m + n)像KMP这样的算法随着字符串变得更长。