-
Notifications
You must be signed in to change notification settings - Fork 0
/
match.go
153 lines (131 loc) · 3.18 KB
/
match.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
package pslog
import (
"bytes"
"gitee.com/xuesongtao/gotool/base"
)
type Matcher interface {
Null() bool
Insert(bytes []byte, target ...*Target)
Search(target []byte) bool
GetTarget(target []byte) (*Target, bool)
}
// *******************************************************************************
// * 普通 *
// *******************************************************************************
// Simple 简单匹配
type Simple struct {
target *Target
match []byte // 待匹配的内容
}
func (s *Simple) Null() bool {
return len(s.match) == 0
}
func (s *Simple) Insert(bytes []byte, target ...*Target) {
s.match = bytes
if len(target) > 0 {
s.target = target[0]
}
}
func (s *Simple) GetTarget(target []byte) (*Target, bool) {
if bytes.Contains(target, s.match) {
return s.target, true && s.target != nil
}
return nil, false
}
func (s *Simple) Search(target []byte) bool {
if s.Null() {
return false
}
return bytes.Contains(target, s.match)
}
// *******************************************************************************
// * 字典树 *
// *******************************************************************************
// 字典树
type Tire struct {
root *node
}
type node struct {
isNull bool // 用于标记 tire 除根以外是否为空, 只在 root node 记录有效
IsRoot bool
IsEnd bool
Data byte
Children map[byte]*node
target *Target
}
func newNode(b byte, root ...bool) *node {
isRoot := false
if len(root) > 0 && root[0] {
isRoot = root[0]
}
obj := &node{
IsRoot: isRoot,
Data: b,
Children: make(map[byte]*node, 1<<4),
}
if isRoot {
obj.isNull = true // 根默认为 null
}
return obj
}
func (n *node) String() string {
return base.ToString(n)
}
func newTire() *Tire {
// 根节点设置为 '/'
return &Tire{root: newNode('/', true)}
}
// null 是否为空
func (t *Tire) Null() bool {
return t.root.isNull
}
// Insert 新增模式串
func (t *Tire) Insert(bytes []byte, target ...*Target) {
if t.Null() { // 如果为空的话, 修改下标记
t.root.isNull = false
}
dataLen := len(bytes)
curNode := t.root
var b byte
for i := 0; i < dataLen; i++ {
b = bytes[i]
if node := curNode.Children[b]; node == nil {
curNode.Children[b] = newNode(b)
}
curNode = curNode.Children[b]
}
curNode.IsEnd = true
if len(target) > 0 {
curNode.target = target[0]
}
}
// Search 查询主串
func (t *Tire) Search(target []byte) bool {
node := t.searchNode(target)
return node.IsEnd
}
// GetTarget 获取 target
func (t *Tire) GetTarget(target []byte) (*Target, bool) {
node := t.searchNode(target)
return node.target, node.IsEnd && node.target != nil
}
func (t *Tire) searchNode(target []byte) *node {
dataLen := len(target)
curNode := t.root
var b byte
for i := 0; i < dataLen; i++ {
b = target[i]
if node := curNode.Children[b]; node == nil {
if curNode.IsEnd { // 匹配
break
}
if !curNode.IsRoot { // 当没有匹配同时不在顶层, 返回顶层
curNode = t.root
}
continue
}
curNode = curNode.Children[b]
}
// plg.Info(curNode)
return curNode
}