package ahocorasick
import (
"fmt"
"time"
)
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) {
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,
}
}
func BuildExtendedAc(p []string) (acToReturn map[int]map[uint8]int, f map[int][]int) {
acTrie, stateIsTerminal, f := ConstructTrie(p)
s := make([]int, len(stateIsTerminal))
i := 0
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]])
}
} else {
s[current] = i
}
}
a := ComputeAlphabet(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
}