chore: refactor (#2875)

This commit is contained in:
Kevin Wan
2023-02-12 22:20:36 +08:00
committed by kevin
parent 95d7c73409
commit 016d965f56
3 changed files with 49 additions and 30 deletions

View File

@@ -100,11 +100,77 @@ 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 ( for i := len(paths); i < len(chars); i++ {
result *node char := chars[i]
start int child, ok := cur.children[char]
) if ok {
cur = child
if cur.end {
longestMatched = cur
}
paths = append(paths, cur)
} else {
if longestMatched != nil {
return 0, longestMatched.depth, nil
}
if n.end {
return 0, n.depth, nil
}
// new path match
var jump *node
// old path pre longest preMatch
preMatch, preStart := findMatch(paths)
icur := cur
for icur.fail != nil {
jump, ok = icur.fail.children[char]
if ok {
break
}
icur = icur.fail
}
switch {
case preMatch != nil && jump != nil:
if jumpStart := i - jump.depth + 1; preStart < jumpStart {
return preStart, preMatch.depth, nil
} else {
return jumpStart, 0, append(paths[jumpStart:], jump)
}
case preMatch != nil && jump == nil:
return preStart, preMatch.depth, nil
case preMatch == nil && jump != nil:
return i - jump.depth + 1, 0, append(paths[i-jump.depth+1:], jump)
case preMatch == nil && jump == nil:
return i + 1, 0, nil
}
}
}
// this longest matched node
if longestMatched != nil {
return 0, longestMatched.depth, nil
}
if n.end {
return 0, n.depth, nil
}
match, start := findMatch(paths)
if match != nil {
return start, match.depth, 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-- { for i := len(path) - 1; i >= 0; i-- {
icur := path[i] icur := path[i]
var cur *node var cur *node
@@ -125,63 +191,6 @@ func (n *node) longestMatch(chars []rune, paths []*node) (uselessLen, matchLen i
} }
} }
} }
return result, start
}
for i := len(paths); i < len(chars); i++ { return result, start
char := chars[i]
child, ok := cur.children[char]
if ok {
cur = child
if cur.end {
longestMatched = cur
}
paths = append(paths, cur)
} else {
if longestMatched != nil {
return 0, longestMatched.depth, nil
}
if n.end {
return 0, n.depth, nil
}
// old path pre longest preMatch
preMatch, preStart := findMatch(paths)
// new path match
var jump *node
icur := cur
for icur.fail != nil {
jump, ok = icur.fail.children[char]
if ok {
break
}
icur = icur.fail
}
switch {
case preMatch != nil && jump != nil:
if jumpStart := i - jump.depth + 1; preStart < jumpStart {
return preStart, preMatch.depth, nil
} else {
return jumpStart, 0, append(paths[jumpStart:], jump)
}
case preMatch != nil && jump == nil:
return preStart, preMatch.depth, nil
case preMatch == nil && jump != nil:
return i - jump.depth + 1, 0, append(paths[i-jump.depth+1:], jump)
case preMatch == nil && jump == nil:
return i + 1, 0, nil
}
}
}
// this longest matched node
if longestMatched != nil {
return 0, longestMatched.depth, nil
}
if n.end {
return 0, n.depth, nil
}
match, start := findMatch(paths)
if match != nil {
return start, match.depth, nil
}
return len(chars), 0, nil
} }

View File

@@ -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()
} }

View File

@@ -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("日本的首都是东京"))
}