github.com/lingyao2333/mo-zero@v1.4.1/core/stringx/node.go (about) 1 package stringx 2 3 type node struct { 4 children map[rune]*node 5 fail *node 6 depth int 7 end bool 8 } 9 10 func (n *node) add(word string) { 11 chars := []rune(word) 12 if len(chars) == 0 { 13 return 14 } 15 16 nd := n 17 var depth int 18 for i, char := range chars { 19 if nd.children == nil { 20 child := new(node) 21 child.depth = i + 1 22 nd.children = map[rune]*node{char: child} 23 nd = child 24 } else if child, ok := nd.children[char]; ok { 25 nd = child 26 depth++ 27 } else { 28 child := new(node) 29 child.depth = i + 1 30 nd.children[char] = child 31 nd = child 32 } 33 } 34 35 nd.end = true 36 } 37 38 func (n *node) build() { 39 var nodes []*node 40 for _, child := range n.children { 41 child.fail = n 42 nodes = append(nodes, child) 43 } 44 for len(nodes) > 0 { 45 nd := nodes[0] 46 nodes = nodes[1:] 47 for key, child := range nd.children { 48 nodes = append(nodes, child) 49 cur := nd 50 for cur != nil { 51 if cur.fail == nil { 52 child.fail = n 53 break 54 } 55 if fail, ok := cur.fail.children[key]; ok { 56 child.fail = fail 57 break 58 } 59 cur = cur.fail 60 } 61 } 62 } 63 } 64 65 func (n *node) find(chars []rune) []scope { 66 var scopes []scope 67 size := len(chars) 68 cur := n 69 70 for i := 0; i < size; i++ { 71 child, ok := cur.children[chars[i]] 72 if ok { 73 cur = child 74 } else { 75 for cur != n { 76 cur = cur.fail 77 if child, ok = cur.children[chars[i]]; ok { 78 cur = child 79 break 80 } 81 } 82 83 if child == nil { 84 continue 85 } 86 } 87 88 for child != n { 89 if child.end { 90 scopes = append(scopes, scope{ 91 start: i + 1 - child.depth, 92 stop: i + 1, 93 }) 94 } 95 child = child.fail 96 } 97 } 98 99 return scopes 100 }