Java 中 String.contains() 的大 O 是啥?

Posted

技术标签:

【中文标题】Java 中 String.contains() 的大 O 是啥?【英文标题】:What is the Big-O of String.contains() in Java?Java 中 String.contains() 的大 O 是什么? 【发布时间】:2011-05-04 14:59:14 【问题描述】:

我正在做一个项目,需要优化运行时间。 String.contains() runtime 是不是和TreeSet.contains()一样,都是O(logN)?

我问的原因是我正在构建一个TreeMap<String, TreeSet<Song>>,其中 Songs 包含一串歌词。根据效率,我正在考虑在歌曲中包含一组歌词,并在其上而不是字符串上运行搜索。

【问题讨论】:

不想成为一个混蛋或其他什么,但:为什么不分析它? 如果我有时间做测试,也许吧。我想在项目中运行另一个测试:treeset 和 hashset 之间的运行时变化。如果一天有 30 小时,那么时间还不够! 【参考方案1】:

最著名的算法之一是 Boyer-Moore 字符串搜索算法,虽然它可以在最好的情况下提供次线性性能,但它是 O(n)。

在 Java 中使用哪种算法取决于您下载的实现。例如,OpenJDK 似乎使用了一种在 O(nm) 中运行的简单算法,并且在最佳情况下具有线性性能。请参阅第 1770-1806 行 here。

【讨论】:

您链接到的文章说它是 O(n),因为它最多进行 3n 次比较。 “最坏情况 O(n)”是重言式 - 根据定义 O(n) 是最坏情况 :) 根据programmers.stackexchange.com/questions/65558/…,jdk1.6.0_23 具有与当代 OpenJDK 相同的 String.indexOf() 实现。有人可以告诉你String.contains() 是否属实 @NicholasWhite O(n) 是一个上限。它可能是最坏情况、平均情况或最佳情况性能的上限。上限和下限与最佳/平均/最差情况正交。另一个正交维度是loose vs. tight。 O(n) 是一个宽松的上限。 Θ(n) 是一个严格的上限和下限。【参考方案2】:

.contains() 绝对使用幼稚的方法,相当于O(nm) 的时间复杂度。

Boyer-moore 在最坏的情况下需要 O(nm) 时间。 KMP 在最坏的情况下需要 O(n) 时间。

在与模式匹配相关的问题之一中,我使用了.contains(),它花费了70 ms,而用patternSearch() //KMP search 替换该行将时间减少到14 ms

Java source code | KMP search vs .contains()

【讨论】:

KMP 最坏情况是 O(n + m),因为您需要事先创建 lsp 表。 是的,但即使在最坏的情况下n==m -> O(n+m) -> O(2n) -> O(n)【参考方案3】:

您也可以尝试使用 Trie 代替 TreeMap(尽管 Java 没有内置的 Trie 实现)

【讨论】:

Trie reference 似乎 Trie 只支持“starts with”,不支持“contains”?

以上是关于Java 中 String.contains() 的大 O 是啥?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Java 中的 String.contains() 方法中使用正则表达式

在 .Net Standard 2.0 中替换 string.Contains(string, StringComparison)

python、pandas中string.contains的反转

java中怎么判断一个字符串中包含某个字符或字符串

string.contains()

为啥 String.Contains 不直接调用最终重载?