In [1]:
import (
"fmt"
"strings"
)
In [2]:
type Node struct {
child map[byte] int
}
type SuffixTrie struct {
t string
nodes []*Node
}
In [3]:
func NewNode() *Node {
node := new (Node)
node.child = make(map[byte] int)
return node
}
func NewSuffixTrie(t string) *SuffixTrie {
st := new(SuffixTrie)
st.nodes = append(st.nodes, NewNode())
for i := 0; i < len(t); i++ {
cur := 0
for _, c := range []byte(t[i:]) {
if node, ok := st.nodes[cur].child[c] ; ok {
cur = node
} else {
st.nodes[cur].child[c] = len(st.nodes)
cur = len(st.nodes)
st.nodes = append(st.nodes, NewNode())
}
}
st.nodes[cur].child['$'] = len(st.nodes)
st.nodes = append(st.nodes, NewNode())
}
return st
}
In [4]:
func (st *SuffixTrie) followPath(s string) int {
// Follow path given by characters of s. Return node at
// end of path, or -1 if we fall off
cur := 0
for _, c := range []byte(s) {
if node, ok := st.nodes[cur].child[c] ; ok {
cur = node
} else {
return -1
}
}
return cur
}
In [5]:
func (st *SuffixTrie) hasSubstring(s string) bool {
// Return true of s appears as a substring of t
return st.followPath(s) >= 0
}
In [6]:
func (st *SuffixTrie) hasSuffix(s string) bool {
// Return true of s appears as a substring of t
cur := st.followPath(s)
_, ok := st.nodes[cur].child['$']
return cur >= 0 && ok
}
In [7]:
func (st *SuffixTrie) toDot() string {
// Return dot representation of trie to make a picture
lines := []string{"igraph \"Suffix trie\" {",
" node [shape=circle label=\"\"];"}
todo := []int{0}
for len(todo) > 0 {
node := todo[0]
todo = todo[1:]
for c, child := range st.nodes[node].child {
lines = append(lines, fmt.Sprintf(" %d -> %d [ label=\"%c\" ];", node, child, c))
todo = append(todo, child)
}
}
lines = append(lines, "}")
return strings.Join(lines, "\n")
}
In [8]:
strie := NewSuffixTrie("there would have been a time for such a word")
In [9]:
strie.hasSubstring("nope")
Out[9]:
In [10]:
strie.hasSubstring("would have been")
Out[10]:
In [11]:
strie.hasSubstring("such a word")
Out[11]:
In [12]:
strie.hasSuffix("would have been")
Out[12]:
In [13]:
strie.hasSuffix("such a word")
Out[13]:
In [14]:
strie2 := NewSuffixTrie("CAT")
strie2.toDot()
Out[14]:
Currently these Go notebooks can't render diagrams; see Python version for the actual tree diagram.