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  }