chore: refactor (#2875)

master
Kevin Wan 2 years ago committed by GitHub
parent cacd5dc91a
commit 072db116c3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -100,33 +100,6 @@ func (n *node) find(chars []rune) []scope {
func (n *node) longestMatch(chars []rune, paths []*node) (uselessLen, matchLen int, nextPaths []*node) { func (n *node) longestMatch(chars []rune, paths []*node) (uselessLen, matchLen int, nextPaths []*node) {
cur := n cur := n
var longestMatched *node var longestMatched *node
findMatch := func(path []*node) (*node, int) {
var (
result *node
start int
)
for i := len(path) - 1; i >= 0; i-- {
icur := path[i]
var cur *node
for icur.fail != nil {
if icur.fail.end {
cur = icur.fail
break
}
icur = icur.fail
}
if cur != nil {
if result == nil {
result = cur
start = i - result.depth + 1
} else if curStart := i - cur.depth + 1; curStart < start {
result = cur
start = curStart
}
}
}
return result, start
}
for i := len(paths); i < len(chars); i++ { for i := len(paths); i < len(chars); i++ {
char := chars[i] char := chars[i]
@ -141,21 +114,25 @@ func (n *node) longestMatch(chars []rune, paths []*node) (uselessLen, matchLen i
if longestMatched != nil { if longestMatched != nil {
return 0, longestMatched.depth, nil return 0, longestMatched.depth, nil
} }
if n.end { if n.end {
return 0, n.depth, nil return 0, n.depth, nil
} }
// old path pre longest preMatch
preMatch, preStart := findMatch(paths)
// new path match // new path match
var jump *node var jump *node
// old path pre longest preMatch
preMatch, preStart := findMatch(paths)
icur := cur icur := cur
for icur.fail != nil { for icur.fail != nil {
jump, ok = icur.fail.children[char] jump, ok = icur.fail.children[char]
if ok { if ok {
break break
} }
icur = icur.fail icur = icur.fail
} }
switch { switch {
case preMatch != nil && jump != nil: case preMatch != nil && jump != nil:
if jumpStart := i - jump.depth + 1; preStart < jumpStart { if jumpStart := i - jump.depth + 1; preStart < jumpStart {
@ -172,16 +149,48 @@ func (n *node) longestMatch(chars []rune, paths []*node) (uselessLen, matchLen i
} }
} }
} }
// this longest matched node // this longest matched node
if longestMatched != nil { if longestMatched != nil {
return 0, longestMatched.depth, nil return 0, longestMatched.depth, nil
} }
if n.end { if n.end {
return 0, n.depth, nil return 0, n.depth, nil
} }
match, start := findMatch(paths) match, start := findMatch(paths)
if match != nil { if match != nil {
return start, match.depth, nil return start, match.depth, nil
} }
return len(chars), 0, nil return len(chars), 0, nil
} }
func findMatch(path []*node) (*node, int) {
var result *node
var start int
for i := len(path) - 1; i >= 0; i-- {
icur := path[i]
var cur *node
for icur.fail != nil {
if icur.fail.end {
cur = icur.fail
break
}
icur = icur.fail
}
if cur != nil {
if result == nil {
result = cur
start = i - result.depth + 1
} else if curStart := i - cur.depth + 1; curStart < start {
result = cur
start = curStart
}
}
}
return result, start
}

@ -33,9 +33,10 @@ func NewReplacer(mapping map[string]string) Replacer {
// Replace replaces text with given substitutes. // Replace replaces text with given substitutes.
func (r *replacer) Replace(text string) string { func (r *replacer) Replace(text string) string {
var buf strings.Builder var buf strings.Builder
var paths []*node
target := []rune(text) target := []rune(text)
cur := r.node cur := r.node
var paths []*node
for len(target) != 0 { for len(target) != 0 {
uselessLen, matchLen, nextPaths := cur.longestMatch(target, paths) uselessLen, matchLen, nextPaths := cur.longestMatch(target, paths)
if uselessLen > 0 { if uselessLen > 0 {
@ -54,5 +55,6 @@ func (r *replacer) Replace(text string) string {
paths = nil paths = nil
} }
} }
return buf.String() return buf.String()
} }

@ -211,3 +211,11 @@ func TestFuzzReplacerCase2(t *testing.T) {
t.Errorf("result: %s, match: %v", val, keys) t.Errorf("result: %s, match: %v", val, keys)
} }
} }
func TestReplacer_ReplaceLongestMatch(t *testing.T) {
replacer := NewReplacer(map[string]string{
"日本的首都": "东京",
"日本": "本日",
})
assert.Equal(t, "东京是东京", replacer.Replace("日本的首都是东京"))
}

Loading…
Cancel
Save