rabin_karp.go 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. // Copyright 2014-2022 Ulrich Kunitz. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package hash
  5. // A is the default constant for Robin-Karp rolling hash. This is a random
  6. // prime.
  7. const A = 0x97b548add41d5da1
  8. // RabinKarp supports the computation of a rolling hash.
  9. type RabinKarp struct {
  10. A uint64
  11. // a^n
  12. aOldest uint64
  13. h uint64
  14. p []byte
  15. i int
  16. }
  17. // NewRabinKarp creates a new RabinKarp value. The argument n defines the
  18. // length of the byte sequence to be hashed. The default constant will will be
  19. // used.
  20. func NewRabinKarp(n int) *RabinKarp {
  21. return NewRabinKarpConst(n, A)
  22. }
  23. // NewRabinKarpConst creates a new RabinKarp value. The argument n defines the
  24. // length of the byte sequence to be hashed. The argument a provides the
  25. // constant used to compute the hash.
  26. func NewRabinKarpConst(n int, a uint64) *RabinKarp {
  27. if n <= 0 {
  28. panic("number of bytes n must be positive")
  29. }
  30. aOldest := uint64(1)
  31. // There are faster methods. For the small n required by the LZMA
  32. // compressor O(n) is sufficient.
  33. for i := 0; i < n; i++ {
  34. aOldest *= a
  35. }
  36. return &RabinKarp{
  37. A: a, aOldest: aOldest,
  38. p: make([]byte, 0, n),
  39. }
  40. }
  41. // Len returns the length of the byte sequence.
  42. func (r *RabinKarp) Len() int {
  43. return cap(r.p)
  44. }
  45. // RollByte computes the hash after x has been added.
  46. func (r *RabinKarp) RollByte(x byte) uint64 {
  47. if len(r.p) < cap(r.p) {
  48. r.h += uint64(x)
  49. r.h *= r.A
  50. r.p = append(r.p, x)
  51. } else {
  52. r.h -= uint64(r.p[r.i]) * r.aOldest
  53. r.h += uint64(x)
  54. r.h *= r.A
  55. r.p[r.i] = x
  56. r.i = (r.i + 1) % cap(r.p)
  57. }
  58. return r.h
  59. }