【问题标题】:Go: polynomial fingerprint for string comparisonGo:用于字符串比较的多项式指纹
【发布时间】:2020-08-17 19:37:07
【问题描述】:

我想实现一个滚动哈希函数来进行字符串比较(Rabin-Karp)

为此,我将输入字符串转换为字节切片(使用 go unicode/utf8)并对其运行“多项式指纹”功能。

例如,我输入字符串qwerty,它转换为[113 119 101 114 116 121] 我用了一个基地256

rune 121, base 256.0, exponent 0, value 121
rune 116, base 256.0, exponent 1, value 29696
rune 114, base 256.0, exponent 2, value 7471104
rune 101, base 256.0, exponent 3, value 1694498816
rune 119, base 256.0, exponent 4, value 511101108224
rune 113, base 256.0, exponent 5, value 124244813938688

我对“多项式指纹”的概念有疑问:很快,基础变得非常大,如何随着用户想要匹配的字符串输入进行扩展?

在我的用例中,因为 Go math.Pow 函数使用 float64 类型,所以在 7 个字符后会变得混乱

rune 114, base 256.0, exponent 7, value 8214565720323784704
rune 101, base 256.0, exponent 8, value -9223372036854775808
rune 119, base 256.0, exponent 9, value -9223372036854775808
rune 113, base 256.0, exponent 10, value -9223372036854775808

我觉得使用 uint64 只会使问题向前一点

【问题讨论】:

  • 您可能希望math/big 包处理大量数据。
  • 您应该对某个 N 取模 N(如果您正在执行简单的滚动哈希,而不是 rabin 指纹识别)。如果您使用的是 rabin 指纹识别,则更加困难,但请参阅:github.com/aclements/go-rabin/tree/master/rabin
  • math.Pow 不适合这个,你根本不需要任何 pow 函数。
  • 我根本不需要任何 pow 函数,你的意思是:只需实现它?我正在看平方乘方

标签: algorithm go math hash rabin-karp


【解决方案1】:

hash函数的思想其实就是会溢出,但是大概率不同的字符串会给出不同的hash。为了使其工作,您需要使用互质数作为运算的基数和模数。您应该使用一些素数基数(大于字母大小)并执行所有操作模数一些素数(尽可能大)(素数将导致最小的碰撞机会)。对此哈希使用整数类型。如果你需要你的字母表至少有 256 个符号,你可以使用 uint64,base 257 并执行所有操作,例如,模数 1012+39

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-12-12
    • 1970-01-01
    • 2022-12-05
    • 1970-01-01
    • 2023-03-15
    • 1970-01-01
    • 2013-02-19
    相关资源
    最近更新 更多