forked from TheAlgorithms/Go
-
Notifications
You must be signed in to change notification settings - Fork 0
/
advancedahocorasick.go
82 lines (77 loc) · 2.41 KB
/
advancedahocorasick.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
package ahocorasick
import (
"fmt"
"time"
)
// Advanced Function performing the Advanced Aho-Corasick algorithm.
// Finds and prints occurrences of each pattern.
func Advanced(t string, p []string) Result {
startTime := time.Now()
occurrences := make(map[int][]int)
ac, f := BuildExtendedAc(p)
current := 0
for pos := 0; pos < len(t); pos++ {
if GetTransition(current, t[pos], ac) != -1 {
current = GetTransition(current, t[pos], ac)
} 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,
}
}
// BuildExtendedAc Functions that builds extended Aho Corasick automaton.
func BuildExtendedAc(p []string) (acToReturn map[int]map[uint8]int, f map[int][]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?
}
}
a := ComputeAlphabet(p) // concat of all patterns in p
for j := range a {
if GetTransition(i, a[j], acToReturn) == -1 {
CreateTransition(i, a[j], i, acToReturn)
}
}
for current := 1; current < len(stateIsTerminal); current++ {
for j := range a {
if GetTransition(current, a[j], acToReturn) == -1 {
CreateTransition(current, a[j], GetTransition(s[current], a[j], acToReturn), acToReturn)
}
}
}
return acToReturn, f
}