字符串比较与散列

Posted

技术标签:

【中文标题】字符串比较与散列【英文标题】:String Comparison vs. Hashing 【发布时间】:2016-04-22 04:53:24 【问题描述】:

我最近了解了rolling hash 数据结构,基本上它的主要用途之一是在字符串中搜索子字符串。以下是我注意到的一些优点:

比较两个字符串的成本可能很高,因此应尽可能避免这种情况 散列字符串并比较散列通常比比较字符串快得多,但是每次重新散列新子字符串通常需要线性时间 滚动散列能够在恒定时间内重新散列新的子字符串,使其更快、更高效地完成此任务

我继续在 javascript 中实现了滚动哈希,并开始分析滚动哈希、传统重新哈希以及仅将子字符串相互比较之间的速度。

在我的发现中,子字符串越大,传统的重新散列方法运行所需的时间就越长(如预期的那样),而滚动散列的运行速度非常快(如预期的那样)。但是,将子字符串比较在一起比滚动哈希要快得多。这怎么可能?

为了方便起见,假设函数在约 240 万个字符串中搜索 100 个字符的子字符串的运行时间如下:

滚动哈希 - 0.809 秒 传统的重新散列 - 71.009 秒 仅比较字符串(无哈希) 0.089 秒

字符串比较怎么会比滚动哈希快这么多?它可能与 JavaScript 特别有关吗?字符串是 JavaScript 中的原始类型;这会导致字符串比较在恒定时间内运行吗?

我的主要困惑是关于字符串比较在 JavaScript 中如何/为什么如此之快,而我的印象是它们应该相对较慢。

注意: 字符串比较我指的是stringA === stringB

注意: 我在Computer Science Community 上问过这个问题,并被告知我也应该在这里问这个问题,因为这很可能是特定于 JavaScript 的。

【问题讨论】:

你的滚动哈希实现是什么样的,也许你可以在jsperf上设置它,这样我们就可以自己测试了。您使用的 javascript 引擎很可能在比较简单字符串方面比您可以用 javascript 编写的任何东西都快得多。 您可以编写自己的字符串comarison并将其与滚动散列进行比较。 我的滚动哈希实现可以在 here 找到,但主要关注的是 JavaScript 中字符串比较的速度有多快。我认为比较字符串应该相对较慢,所以我很困惑为什么/如何在 JavaScript 中如此之快 再一次,这可能取决于实现,这就是引擎是如何用 C++ 等语言编写的,它决定了在使用字符串时,=====indexOf 等比较在内部的速度有多快。 那太好了,一个很好的答案 +1 【参考方案1】:

经过一些测试和分析,我得出的结论是,我的滚动哈希方法运行速度比简单地比较两个字符串要慢一些。


如果滚动哈希声称在恒定时间内运行,它怎么能比比较字符串慢?

函数相对较慢 - 调用函数比简单地executing code inline 稍慢。在我的特殊情况下, 每次滚动哈希时都必须在我的对象上调用函数 重新散列其内部窗口,因此运行时间稍长 与字符串比较相比,因为该代码只是内联的。特别是因为我的基准测试有超过 200 万次迭代的滚动哈希“移位”,所以可以更清楚地看到这个函数减速。

但是为什么字符串比较这么快呢?

字符串是原始的 - 基本上,因为strings are a primitive type in JavaScript,尝试比较两个字符串最 可能会调用一些直接在 口译员。这种低级评估可以与 架构可能可以(类似于比较数字)。


结论

在这种情况下,在 JavaScript 中比较字符串最终会比滚动哈希更快,因为字符串是原始的,因此允许解释器非常快速地处理这些元素,并且因为简单地 调用函数会产生轻微的开销并在很小的范围内减慢进程。

【讨论】:

正是像你这样的人让 Stack Overflow 变得很棒。感谢您撰写此问题和答案。

以上是关于字符串比较与散列的主要内容,如果未能解决你的问题,请参考以下文章

Redis数据操作之字符串与散列键的区别 | Redis

深入理解容器

有效地将给定令牌与数据库中的散列,盐渍令牌进行比较

Java集合—散列与散列码

散列算法与散列码

java 散列与散列码探讨 ,简单HashMap实现散列映射表运行各种操作示列