dfa.go 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. package main
  2. import "sync"
  3. // 多叉树
  4. type (
  5. //MultiTreeNode 多叉树节点
  6. MultiTreeNode struct {
  7. Key rune
  8. End bool
  9. Children map[rune]*MultiTreeNode
  10. }
  11. //MultiTree 多叉树
  12. MultiTree struct {
  13. Root *MultiTreeNode
  14. Lock sync.Mutex // 添加互斥锁
  15. }
  16. //结果
  17. Result struct {
  18. Data string
  19. Start, End int
  20. }
  21. )
  22. func NewMultiTree() *MultiTree {
  23. return &MultiTree{
  24. Root: &MultiTreeNode{
  25. Children: make(map[rune]*MultiTreeNode),
  26. },
  27. }
  28. }
  29. func (mt *MultiTree) Add(segment string) {
  30. mt.Lock.Lock()
  31. defer mt.Lock.Unlock()
  32. path := []rune(segment)
  33. node := mt.Root
  34. pathLen := len(path)
  35. for index, t := range path {
  36. end := index == pathLen-1
  37. if v, ok := node.Children[t]; ok {
  38. node = v
  39. if end { //后加入的词(可能是老词的子集),需要修正属性
  40. node.End = end
  41. }
  42. } else {
  43. leafNode := &MultiTreeNode{
  44. Key: t,
  45. Children: make(map[rune]*MultiTreeNode),
  46. }
  47. if end { //是结束节点
  48. leafNode.End = true
  49. }
  50. node.Children[t] = leafNode
  51. node = leafNode
  52. }
  53. }
  54. }
  55. // Match 匹配 / 查找
  56. func (mt *MultiTree) Match(segment string, maximum bool) []*Result {
  57. mt.Lock.Lock()
  58. defer mt.Lock.Unlock()
  59. var wordNode *MultiTreeNode
  60. node := mt.Root
  61. var ok bool
  62. path := []rune(segment)
  63. ret := make([]*Result, 0, 0)
  64. pos := 0
  65. //找第一层
  66. for pos < len(path) {
  67. if wordNode, ok = node.Children[path[pos]]; !ok {
  68. pos += 1
  69. continue
  70. }
  71. skipStep := 1
  72. for w := pos + 1; w < len(path); w++ {
  73. if wordNode, ok = wordNode.Children[path[w]]; !ok {
  74. break
  75. }
  76. if wordNode.End && !maximum {
  77. return []*Result{
  78. &Result{
  79. Data: string(path[pos : w+1]), Start: pos, End: w + 1},
  80. }
  81. } else if wordNode.End {
  82. ret = append(ret, &Result{
  83. Data: string(path[pos : w+1]), Start: pos, End: w + 1})
  84. skipStep = w - pos
  85. }
  86. }
  87. pos += skipStep
  88. }
  89. return ret
  90. }