This article is continuation of following five articles:
Ukkonen’s Suffix Tree Construction – Part 1
Ukkonen’s Suffix Tree Construction – Part 2
Ukkonen’s Suffix Tree Construction – Part 3
Ukkonen’s Suffix Tree Construction – Part 4
Ukkonen’s Suffix Tree Construction – Part 5
Please go through Part 1, Part 2, Part 3, Part 4 and Part 5, before looking at current article, where we have seen few basics on suffix tree, high level ukkonen’s algorithm, suffix link and three implementation tricks and activePoints along with an example string “abcabxabcd” where we went through all phases of building suffix tree.
Here, we will see the data structure used to represent suffix tree and the code implementation.
At that end of Part 5 article, we have discussed some of the operations we will be doing while building suffix tree and later when we use suffix tree in different applications.
There could be different possible data structures we may think of to fulfill the requirements where some data structure may be slow on some operations and some fast. Here we will use following in our implementation:
We will have SuffixTreeNode structure to represent each node in tree. SuffixTreeNode structure will have following members:
- children – This will be an array of alphabet size. This will store all the children nodes of current node on different edges starting with different characters.
- suffixLink – This will point to other node where current node should point via suffix link.
- start, end – These two will store the edge label details from parent node to current node. (start, end) interval specifies the edge, by which the node is connected to its parent node. Each edge will connect two nodes, one parent and one child, and (start, end) interval of a given edge will be stored in the child node. Lets say there are two nods A (parent) and B (Child) connected by an edge with indices (5, 8) then this indices (5, 8) will be stored in node B.
- suffixIndex – This will be non-negative for leaves and will give index of suffix for the path from root to this leaf. For non-leaf node, it will be -1 .
This data structure will answer to the required queries quickly as below:
- How to check if a node is root ? — Root is a special node, with no parent and so it’s start and end will be -1, for all other nodes, start and end indices will be non-negative.
- How to check if a node is internal or leaf node ? — suffixIndex will help here. It will be -1 for internal node and non-negative for leaf nodes.
- What is the length of path label on some edge? — Each edge will have start and end indices and length of path label will be end-start+1
- What is the path label on some edge ? — If string is S, then path label will be substring of S from start index to end index inclusive, [start, end].
- How to check if there is an outgoing edge for a given character c from a node A ? — If A->children[c] is not NULL, there is a path, if NULL, no path.
- What is the character value on an edge at some given distance d from a node A ? — Character at distance d from node A will be S[A->start + d], where S is the string.
- Where an internal node is pointing via suffix link ? — Node A will point to A->suffixLink
- What is the suffix index on a path from root to leaf ? — If leaf node is A on the path, then suffix index on that path will be A->suffixIndex
Following is C implementation of Ukkonen’s Suffix Tree Construction. The code may look a bit lengthy, probably because of a good amount of comments.
Output (Each edge of Tree, along with suffix index of child node on edge, is printed in DFS order. To understand the output better, match it with the last figure no 43 in previous Part 5 article):
$  ab [-1] c [-1] abxabcd$  d$  xabcd$  b [-1] c [-1] abxabcd$  d$  xabcd$  c [-1] abxabcd$  d$  d$  xabcd$ 
Now we are able to build suffix tree in linear time, we can solve many string problem in efficient way:
- Check if a given pattern P is substring of text T (Useful when text is fixed and pattern changes, KMP otherwise
- Find all occurrences of a given pattern P present in text T
- Find longest repeated substring
- Linear Time Suffix Array Creation
The above basic problems can be solved by DFS traversal on suffix tree.
We will soon post articles on above problems and others like below:
- Build Generalized suffix tree
- Linear Time Longest common substring problem
- Linear Time Longest palindromic substring
Test you understanding?
- Draw suffix tree (with proper suffix link, suffix indices) for string “AABAACAADAABAAABAA$” on paper and see if that matches with code output.
- Every extension must follow one of the three rules: Rule 1, Rule 2 and Rule 3.
Following are the rules applied on five consecutive extensions in some Phase i (i > 5), which ones are valid:
A) Rule 1, Rule 2, Rule 2, Rule 3, Rule 3
B) Rule 1, Rule 2, Rule 2, Rule 3, Rule 2
C) Rule 2, Rule 1, Rule 1, Rule 3, Rule 3
D) Rule 1, Rule 1, Rule 1, Rule 1, Rule 1
E) Rule 2, Rule 2, Rule 2, Rule 2, Rule 2
F) Rule 3, Rule 3, Rule 3, Rule 3, Rule 3
- What are the valid sequences in above for Phase 5
- Every internal node MUST have it’s suffix link set to another node (internal or root). Can a newly created node point to already existing internal node or not ? Can it happen that a new node created in extension j, may not get it’s right suffix link in next extension j+1 and get the right one in later extensions like j+2, j+3 etc ?
- Try solving the basic problems discussed above.
We have published following articles on suffix tree applications:
- Suffix Tree Application 1 – Substring Check
- Suffix Tree Application 2 – Searching All Patterns
- Suffix Tree Application 3 – Longest Repeated Substring
- Suffix Tree Application 4 – Build Linear Time Suffix Array
- Generalized Suffix Tree 1
- Suffix Tree Application 5 – Longest Common Substring
- Suffix Tree Application 6 – Longest Palindromic Substring