Skip to content

Commit 2abcd01

Browse files
committed
internal/bytealg: naive attempt to copy the main Go 1.15 implementatation
Signed-off-by: deadprogram <[email protected]>
1 parent 29f599b commit 2abcd01

File tree

1 file changed

+127
-0
lines changed

1 file changed

+127
-0
lines changed

src/internal/bytealg/bytealg.go

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,3 +124,130 @@ func IndexString(str, sub string) int {
124124
}
125125
return -1
126126
}
127+
128+
// Copyright 2020 The Go Authors. All rights reserved.
129+
// Use of this source code is governed by a BSD-style
130+
// license that can be found in the LICENSE file.
131+
132+
// The following code has been copied from the Go 1.15 release tree.
133+
134+
// PrimeRK is the prime base used in Rabin-Karp algorithm.
135+
const PrimeRK = 16777619
136+
137+
// HashStrBytes returns the hash and the appropriate multiplicative
138+
// factor for use in Rabin-Karp algorithm.
139+
func HashStrBytes(sep []byte) (uint32, uint32) {
140+
hash := uint32(0)
141+
for i := 0; i < len(sep); i++ {
142+
hash = hash*PrimeRK + uint32(sep[i])
143+
}
144+
var pow, sq uint32 = 1, PrimeRK
145+
for i := len(sep); i > 0; i >>= 1 {
146+
if i&1 != 0 {
147+
pow *= sq
148+
}
149+
sq *= sq
150+
}
151+
return hash, pow
152+
}
153+
154+
// HashStr returns the hash and the appropriate multiplicative
155+
// factor for use in Rabin-Karp algorithm.
156+
func HashStr(sep string) (uint32, uint32) {
157+
hash := uint32(0)
158+
for i := 0; i < len(sep); i++ {
159+
hash = hash*PrimeRK + uint32(sep[i])
160+
}
161+
var pow, sq uint32 = 1, PrimeRK
162+
for i := len(sep); i > 0; i >>= 1 {
163+
if i&1 != 0 {
164+
pow *= sq
165+
}
166+
sq *= sq
167+
}
168+
return hash, pow
169+
}
170+
171+
// HashStrRevBytes returns the hash of the reverse of sep and the
172+
// appropriate multiplicative factor for use in Rabin-Karp algorithm.
173+
func HashStrRevBytes(sep []byte) (uint32, uint32) {
174+
hash := uint32(0)
175+
for i := len(sep) - 1; i >= 0; i-- {
176+
hash = hash*PrimeRK + uint32(sep[i])
177+
}
178+
var pow, sq uint32 = 1, PrimeRK
179+
for i := len(sep); i > 0; i >>= 1 {
180+
if i&1 != 0 {
181+
pow *= sq
182+
}
183+
sq *= sq
184+
}
185+
return hash, pow
186+
}
187+
188+
// HashStrRev returns the hash of the reverse of sep and the
189+
// appropriate multiplicative factor for use in Rabin-Karp algorithm.
190+
func HashStrRev(sep string) (uint32, uint32) {
191+
hash := uint32(0)
192+
for i := len(sep) - 1; i >= 0; i-- {
193+
hash = hash*PrimeRK + uint32(sep[i])
194+
}
195+
var pow, sq uint32 = 1, PrimeRK
196+
for i := len(sep); i > 0; i >>= 1 {
197+
if i&1 != 0 {
198+
pow *= sq
199+
}
200+
sq *= sq
201+
}
202+
return hash, pow
203+
}
204+
205+
// IndexRabinKarpBytes uses the Rabin-Karp search algorithm to return the index of the
206+
// first occurence of substr in s, or -1 if not present.
207+
func IndexRabinKarpBytes(s, sep []byte) int {
208+
// Rabin-Karp search
209+
hashsep, pow := HashStrBytes(sep)
210+
n := len(sep)
211+
var h uint32
212+
for i := 0; i < n; i++ {
213+
h = h*PrimeRK + uint32(s[i])
214+
}
215+
if h == hashsep && Equal(s[:n], sep) {
216+
return 0
217+
}
218+
for i := n; i < len(s); {
219+
h *= PrimeRK
220+
h += uint32(s[i])
221+
h -= pow * uint32(s[i-n])
222+
i++
223+
if h == hashsep && Equal(s[i-n:i], sep) {
224+
return i - n
225+
}
226+
}
227+
return -1
228+
}
229+
230+
// IndexRabinKarp uses the Rabin-Karp search algorithm to return the index of the
231+
// first occurence of substr in s, or -1 if not present.
232+
func IndexRabinKarp(s, substr string) int {
233+
// Rabin-Karp search
234+
hashss, pow := HashStr(substr)
235+
n := len(substr)
236+
var h uint32
237+
for i := 0; i < n; i++ {
238+
h = h*PrimeRK + uint32(s[i])
239+
}
240+
if h == hashss && s[:n] == substr {
241+
return 0
242+
}
243+
for i := n; i < len(s); {
244+
h *= PrimeRK
245+
h += uint32(s[i])
246+
h -= pow * uint32(s[i-n])
247+
i++
248+
if h == hashss && s[i-n:i] == substr {
249+
return i - n
250+
}
251+
}
252+
return -1
253+
}

0 commit comments

Comments
 (0)