node.go 1.6 KB

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