forked from TheAlgorithms/Go
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ahocorasick.go
77 lines (72 loc) · 2.19 KB
/
ahocorasick.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
package ahocorasick
import (
"fmt"
"time"
)
// Result structure to hold occurrences
type Result struct {
occurrences map[string][]int
}
// AhoCorasick Function performing the Basic Aho-Corasick algorithm.
// Finds and prints occurrences of each pattern.
func AhoCorasick(t string, p []string) Result {
startTime := time.Now()
occurrences := make(map[int][]int)
ac, f, s := BuildAc(p)
current := 0
for pos := 0; pos < len(t); pos++ {
for GetTransition(current, t[pos], ac) == -1 && s[current] != -1 {
current = s[current]
}
if GetTransition(current, t[pos], ac) != -1 {
current = GetTransition(current, t[pos], ac)
fmt.Printf(" (Continue) \n")
} else {
current = 0
}
_, ok := f[current]
if ok {
for i := range f[current] {
if p[f[current][i]] == GetWord(pos-len(p[f[current][i]])+1, pos, t) { //check for word match
newOccurrences := IntArrayCapUp(occurrences[f[current][i]])
occurrences[f[current][i]] = newOccurrences
occurrences[f[current][i]][len(newOccurrences)-1] = pos - len(p[f[current][i]]) + 1
}
}
}
}
elapsed := time.Since(startTime)
fmt.Printf("\n\nElapsed %f secs\n", elapsed.Seconds())
var resultOccurrences = make(map[string][]int)
for key, value := range occurrences {
resultOccurrences[p[key]] = value
}
return Result{
resultOccurrences,
}
}
// Functions that builds Aho Corasick automaton.
func BuildAc(p []string) (acToReturn map[int]map[uint8]int, f map[int][]int, s []int) {
acTrie, stateIsTerminal, f := ConstructTrie(p)
s = make([]int, len(stateIsTerminal)) //supply function
i := 0 //root of acTrie
acToReturn = acTrie
s[i] = -1
for current := 1; current < len(stateIsTerminal); current++ {
o, parent := GetParent(current, acTrie)
down := s[parent]
for StateExists(down, acToReturn) && GetTransition(down, o, acToReturn) == -1 {
down = s[down]
}
if StateExists(down, acToReturn) {
s[current] = GetTransition(down, o, acToReturn)
if stateIsTerminal[s[current]] {
stateIsTerminal[current] = true
f[current] = ArrayUnion(f[current], f[s[current]]) //F(Current) <- F(Current) union F(S(Current))
}
} else {
s[current] = i //initial state?
}
}
return acToReturn, f, s
}