1
0
mirror of https://github.com/golang/go synced 2024-11-18 11:55:01 -07:00

strings: use Index in Count

This simplifies code and provides performance iprovments:
Similar to https://go-review.googlesource.com/#/c/28577

CountHard1-48               1.74ms ±14%  0.17ms ±14%  -90.16%  (p=0.000 n=19+19)
CountHard2-48               1.78ms ±15%  0.25ms ±13%  -86.10%  (p=0.000 n=19+20)
CountHard3-48               1.78ms ±12%  0.80ms ±11%  -55.19%  (p=0.000 n=17+20)
CountTorture-48             13.5µs ±14%  13.6µs ±11%     ~     (p=0.625 n=18+19)
CountTortureOverlapping-48  6.92ms ±13%  8.42ms ±11%  +21.72%  (p=0.000 n=19+17)

Change-Id: Ief120aee918a66487c76be56e0796871c8502f89
Reviewed-on: https://go-review.googlesource.com/28586
Run-TryBot: Ilya Tocar <ilya.tocar@intel.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
Ilya Tocar 2016-09-07 16:35:32 +03:00 committed by Brad Fitzpatrick
parent 86b2f29676
commit 6347367be3

View File

@ -77,48 +77,18 @@ func hashStrRev(sep string) (uint32, uint32) {
func Count(s, sep string) int {
n := 0
// special cases
switch {
case len(sep) == 0:
if len(sep) == 0 {
return utf8.RuneCountInString(s) + 1
case len(sep) == 1:
// special case worth making fast
c := sep[0]
for i := 0; i < len(s); i++ {
if s[i] == c {
n++
}
}
return n
case len(sep) > len(s):
return 0
case len(sep) == len(s):
if sep == s {
return 1
}
return 0
}
// Rabin-Karp search
hashsep, pow := hashStr(sep)
h := uint32(0)
for i := 0; i < len(sep); i++ {
h = h*primeRK + uint32(s[i])
}
lastmatch := 0
if h == hashsep && s[:len(sep)] == sep {
offset := 0
for {
i := Index(s[offset:], sep)
if i == -1 {
return n
}
n++
lastmatch = len(sep)
offset += i + len(sep)
}
for i := len(sep); i < len(s); {
h *= primeRK
h += uint32(s[i])
h -= pow * uint32(s[i-len(sep)])
i++
if h == hashsep && lastmatch <= i-len(sep) && s[i-len(sep):i] == sep {
n++
lastmatch = i
}
}
return n
}
// Contains reports whether substr is within s.