package main import "sync" // 多叉树 type ( //MultiTreeNode 多叉树节点 MultiTreeNode struct { Key rune End bool Children map[rune]*MultiTreeNode } //MultiTree 多叉树 MultiTree struct { Root *MultiTreeNode Lock sync.Mutex // 添加互斥锁 } //结果 Result struct { Data string Start, End int } ) func NewMultiTree() *MultiTree { return &MultiTree{ Root: &MultiTreeNode{ Children: make(map[rune]*MultiTreeNode), }, } } func (mt *MultiTree) Add(segment string) { mt.Lock.Lock() defer mt.Lock.Unlock() path := []rune(segment) node := mt.Root pathLen := len(path) for index, t := range path { end := index == pathLen-1 if v, ok := node.Children[t]; ok { node = v if end { //后加入的词(可能是老词的子集),需要修正属性 node.End = end } } else { leafNode := &MultiTreeNode{ Key: t, Children: make(map[rune]*MultiTreeNode), } if end { //是结束节点 leafNode.End = true } node.Children[t] = leafNode node = leafNode } } } // Match 匹配 / 查找 func (mt *MultiTree) Match(segment string, maximum bool) []*Result { mt.Lock.Lock() defer mt.Lock.Unlock() var wordNode *MultiTreeNode node := mt.Root var ok bool path := []rune(segment) ret := make([]*Result, 0, 0) pos := 0 //找第一层 for pos < len(path) { if wordNode, ok = node.Children[path[pos]]; !ok { pos += 1 continue } skipStep := 1 for w := pos + 1; w < len(path); w++ { if wordNode, ok = wordNode.Children[path[w]]; !ok { break } if wordNode.End && !maximum { return []*Result{ &Result{ Data: string(path[pos : w+1]), Start: pos, End: w + 1}, } } else if wordNode.End { ret = append(ret, &Result{ Data: string(path[pos : w+1]), Start: pos, End: w + 1}) skipStep = w - pos } } pos += skipStep } return ret }