字符串哈希是一种将字符串转化为哈希数字的技术。为什么我们需要它?有时候比较大的字符串,不需要比较字符串可以比较其生成的散列数。
想像一下,你需要比较下面的👇的两行字符串:

  1. const A = "imagine that this is a string of 200 characters"
  2. const B = "imagine that this is a string of 200 characterz"

想像一下他们有200个字符。比较它们是否相等,你可以使用一个暴力的方法比较每一个字符是否相等。就像下面这样:

  1. const A = "imagine that this is a string of 200 characters"
  2. const B = "imagine that this is a string of 200 characterz"
  3. function equal(A, B) {
  4. let i;
  5. for(i = 0; i < A.length; i++){
  6. if (A[i] !== B[i]) {
  7. return false;
  8. }
  9. }
  10. return true;
  11. }
  12. console.log(equal(A,B));

对于大字符串的比较这不是最理想的,算法复杂度是O(min(A, B))。
当然我们可以添加条件比较A与B的大小,使它变成O(n)。就像这样:

  1. function equal(A, B) {
  2. if (A.lenght !== B.length) return false;
  3. let i;
  4. for(i = 0; i < A.length; i++){
  5. if (A[i] !== B[i]) {
  6. return false;
  7. }
  8. }
  9. return true;
  10. }

正如我所说的,最差也就是O(n)。试想一下比较一个大小不等的字符串呢?
字符串哈希是一个技术,它将我们的字符串转化为一个整数,作为散列数。因此,我们将比较两个哈希值hash(A) == hash(B),算法复杂度是O(1)。这是比较两个字符串最好的选择。

字符串哈希的公式

字符串哈希---帮助你操作字符的强大算法 - 图1
pm是素数,s[0], s[1], s[2]…是每一个字符的值。在这种情况下字符的值是字符编码。
p:它是一个素数,大致等于使用的不同字符数。比如,我们要计算的这个单词的哈希只包含英文字母表中的小写字母,31是一个很好的数字。然而,我们要是包含大写字母53是一个很好的选择。
m: 生成两个随机数,数字越大,出现相同的概率就越小。这个变量也应该是一个☝️素数。10 ^9 + 9是一个常见的选择。
例如:

  1. p = 31
  2. m = 1e9 + 9
  3. word = 'apple'

我们想知道单词apple的哈希值,将数据带入到公式中,就像这样:
字符串哈希---帮助你操作字符的强大算法 - 图2
接着:
字符串哈希---帮助你操作字符的强大算法 - 图3
字符编码的值:

  1. "a" = 97
  2. "p" = 112
  3. "p" = 112
  4. "l" = 108
  5. "e" = 101

替换公式:
字符串哈希---帮助你操作字符的强大算法 - 图4
字符串哈希---帮助你操作字符的强大算法 - 图5
最终:
字符串哈希---帮助你操作字符的强大算法 - 图6
可以得出单词apple的哈希值是96604250。
使用JavaScript实现:

  1. function hash(word) {
  2. var p = 31;
  3. var m = 1e9 + 9;
  4. var hash_value = 0;
  5. for(var i = 0; i < word.length; i++) {
  6. var letter = word[i];
  7. var charCode = letter.charCodeAt();
  8. hash_value = hash_value + (charCode * Math.pow(p, i))
  9. }
  10. return hash_value % m;
  11. }
  12. console.log(hash("apple"));

原文:https://jorgechavez.dev/2020/11/12/string-hashing/