internal/bytealg: naive attempt to copy the main Go 1.15 implementatation
Signed-off-by: deadprogram <ron@hybridgroup.com>
Этот коммит содержится в:
родитель
f4e8ea0d23
коммит
9575fe628f
1 изменённых файлов: 127 добавлений и 0 удалений
|
@ -124,3 +124,130 @@ func IndexString(str, sub string) int {
|
||||||
}
|
}
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Copyright 2020 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// The following code has been copied from the Go 1.15 release tree.
|
||||||
|
|
||||||
|
// PrimeRK is the prime base used in Rabin-Karp algorithm.
|
||||||
|
const PrimeRK = 16777619
|
||||||
|
|
||||||
|
// HashStrBytes returns the hash and the appropriate multiplicative
|
||||||
|
// factor for use in Rabin-Karp algorithm.
|
||||||
|
func HashStrBytes(sep []byte) (uint32, uint32) {
|
||||||
|
hash := uint32(0)
|
||||||
|
for i := 0; i < len(sep); i++ {
|
||||||
|
hash = hash*PrimeRK + uint32(sep[i])
|
||||||
|
}
|
||||||
|
var pow, sq uint32 = 1, PrimeRK
|
||||||
|
for i := len(sep); i > 0; i >>= 1 {
|
||||||
|
if i&1 != 0 {
|
||||||
|
pow *= sq
|
||||||
|
}
|
||||||
|
sq *= sq
|
||||||
|
}
|
||||||
|
return hash, pow
|
||||||
|
}
|
||||||
|
|
||||||
|
// HashStr returns the hash and the appropriate multiplicative
|
||||||
|
// factor for use in Rabin-Karp algorithm.
|
||||||
|
func HashStr(sep string) (uint32, uint32) {
|
||||||
|
hash := uint32(0)
|
||||||
|
for i := 0; i < len(sep); i++ {
|
||||||
|
hash = hash*PrimeRK + uint32(sep[i])
|
||||||
|
}
|
||||||
|
var pow, sq uint32 = 1, PrimeRK
|
||||||
|
for i := len(sep); i > 0; i >>= 1 {
|
||||||
|
if i&1 != 0 {
|
||||||
|
pow *= sq
|
||||||
|
}
|
||||||
|
sq *= sq
|
||||||
|
}
|
||||||
|
return hash, pow
|
||||||
|
}
|
||||||
|
|
||||||
|
// HashStrRevBytes returns the hash of the reverse of sep and the
|
||||||
|
// appropriate multiplicative factor for use in Rabin-Karp algorithm.
|
||||||
|
func HashStrRevBytes(sep []byte) (uint32, uint32) {
|
||||||
|
hash := uint32(0)
|
||||||
|
for i := len(sep) - 1; i >= 0; i-- {
|
||||||
|
hash = hash*PrimeRK + uint32(sep[i])
|
||||||
|
}
|
||||||
|
var pow, sq uint32 = 1, PrimeRK
|
||||||
|
for i := len(sep); i > 0; i >>= 1 {
|
||||||
|
if i&1 != 0 {
|
||||||
|
pow *= sq
|
||||||
|
}
|
||||||
|
sq *= sq
|
||||||
|
}
|
||||||
|
return hash, pow
|
||||||
|
}
|
||||||
|
|
||||||
|
// HashStrRev returns the hash of the reverse of sep and the
|
||||||
|
// appropriate multiplicative factor for use in Rabin-Karp algorithm.
|
||||||
|
func HashStrRev(sep string) (uint32, uint32) {
|
||||||
|
hash := uint32(0)
|
||||||
|
for i := len(sep) - 1; i >= 0; i-- {
|
||||||
|
hash = hash*PrimeRK + uint32(sep[i])
|
||||||
|
}
|
||||||
|
var pow, sq uint32 = 1, PrimeRK
|
||||||
|
for i := len(sep); i > 0; i >>= 1 {
|
||||||
|
if i&1 != 0 {
|
||||||
|
pow *= sq
|
||||||
|
}
|
||||||
|
sq *= sq
|
||||||
|
}
|
||||||
|
return hash, pow
|
||||||
|
}
|
||||||
|
|
||||||
|
// IndexRabinKarpBytes uses the Rabin-Karp search algorithm to return the index of the
|
||||||
|
// first occurence of substr in s, or -1 if not present.
|
||||||
|
func IndexRabinKarpBytes(s, sep []byte) int {
|
||||||
|
// Rabin-Karp search
|
||||||
|
hashsep, pow := HashStrBytes(sep)
|
||||||
|
n := len(sep)
|
||||||
|
var h uint32
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
h = h*PrimeRK + uint32(s[i])
|
||||||
|
}
|
||||||
|
if h == hashsep && Equal(s[:n], sep) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
for i := n; i < len(s); {
|
||||||
|
h *= PrimeRK
|
||||||
|
h += uint32(s[i])
|
||||||
|
h -= pow * uint32(s[i-n])
|
||||||
|
i++
|
||||||
|
if h == hashsep && Equal(s[i-n:i], sep) {
|
||||||
|
return i - n
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
// IndexRabinKarp uses the Rabin-Karp search algorithm to return the index of the
|
||||||
|
// first occurence of substr in s, or -1 if not present.
|
||||||
|
func IndexRabinKarp(s, substr string) int {
|
||||||
|
// Rabin-Karp search
|
||||||
|
hashss, pow := HashStr(substr)
|
||||||
|
n := len(substr)
|
||||||
|
var h uint32
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
h = h*PrimeRK + uint32(s[i])
|
||||||
|
}
|
||||||
|
if h == hashss && s[:n] == substr {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
for i := n; i < len(s); {
|
||||||
|
h *= PrimeRK
|
||||||
|
h += uint32(s[i])
|
||||||
|
h -= pow * uint32(s[i-n])
|
||||||
|
i++
|
||||||
|
if h == hashss && s[i-n:i] == substr {
|
||||||
|
return i - n
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче