Task: Suffix tree



C#: using System;
using System.Collections.Generic;

namespace SuffixTree {
    class Node {
        public string sub;                     
        public List<int> ch = new List<int>(); 

        public Node() {
            sub = "";
        }

        public Node(string sub, params int[] children) {
            this.sub = sub;
            ch.AddRange(children);
        }
    }

    class SuffixTree {
        readonly List<Node> nodes = new List<Node>();

        public SuffixTree(string str) {
            nodes.Add(new Node());
            for (int i = 0; i < str.Length; i++) {
                AddSuffix(str.Substring(i));
            }
        }

        public void Visualize() {
            if (nodes.Count == 0) {
                Console.WriteLine("<empty>");
                return;
            }

            void f(int n, string pre) {
                var children = nodes[n].ch;
                if (children.Count == 0) {
                    Console.WriteLine("- {0}", nodes[n].sub);
                    return;
                }
                Console.WriteLine("+ {0}", nodes[n].sub);

                var it = children.GetEnumerator();
                if (it.MoveNext()) {
                    do {
                        var cit = it;
                        if (!cit.MoveNext()) break;

                        Console.Write("{0}+-", pre);
                        f(it.Current, pre + "| ");
                    } while (it.MoveNext());
                }

                Console.Write("{0}+-", pre);
                f(children[children.Count-1], pre+"  ");
            }

            f(0, "");
        }

        private void AddSuffix(string suf) {
            int n = 0;
            int i = 0;
            while (i < suf.Length) {
                char b = suf[i];
                int x2 = 0;
                int n2;
                while (true) {
                    var children = nodes[n].ch;
                    if (x2 == children.Count) {
                        
                        n2 = nodes.Count;
                        nodes.Add(new Node(suf.Substring(i)));
                        nodes[n].ch.Add(n2);
                        return;
                    }
                    n2 = children[x2];
                    if (nodes[n2].sub[0] == b) {
                        break;
                    }
                    x2++;
                }
                
                var sub2 = nodes[n2].sub;
                int j = 0;
                while (j < sub2.Length) {
                    if (suf[i + j] != sub2[j]) {
                        
                        var n3 = n2;
                        
                        n2 = nodes.Count;
                        nodes.Add(new Node(sub2.Substring(0, j), n3));
                        nodes[n3].sub = sub2.Substring(j); 
                        nodes[n].ch[x2] = n2;
                        break; 
                    }
                    j++;
                }
                i += j; 
                n = n2; 
            }
        }
    }

    class Program {
        static void Main() {
            new SuffixTree("banana$").Visualize();
        }
    }
}



Java: import java.util.ArrayList;
import java.util.List;

public class SuffixTreeProblem {
    private static class Node {
        String sub = "";                       
        List<Integer> ch = new ArrayList<>();  
    }

    private static class SuffixTree {
        private List<Node> nodes = new ArrayList<>();

        public SuffixTree(String str) {
            nodes.add(new Node());
            for (int i = 0; i < str.length(); ++i) {
                addSuffix(str.substring(i));
            }
        }

        private void addSuffix(String suf) {
            int n = 0;
            int i = 0;
            while (i < suf.length()) {
                char b = suf.charAt(i);
                List<Integer> children = nodes.get(n).ch;
                int x2 = 0;
                int n2;
                while (true) {
                    if (x2 == children.size()) {
                        
                        n2 = nodes.size();
                        Node temp = new Node();
                        temp.sub = suf.substring(i);
                        nodes.add(temp);
                        children.add(n2);
                        return;
                    }
                    n2 = children.get(x2);
                    if (nodes.get(n2).sub.charAt(0) == b) break;
                    x2++;
                }
                
                String sub2 = nodes.get(n2).sub;
                int j = 0;
                while (j < sub2.length()) {
                    if (suf.charAt(i + j) != sub2.charAt(j)) {
                        
                        int n3 = n2;
                        
                        n2 = nodes.size();
                        Node temp = new Node();
                        temp.sub = sub2.substring(0, j);
                        temp.ch.add(n3);
                        nodes.add(temp);
                        nodes.get(n3).sub = sub2.substring(j);  
                        nodes.get(n).ch.set(x2, n2);
                        break;  
                    }
                    j++;
                }
                i += j;  
                n = n2;  
            }
        }

        public void visualize() {
            if (nodes.isEmpty()) {
                System.out.println("<empty>");
                return;
            }
            visualize_f(0, "");
        }

        private void visualize_f(int n, String pre) {
            List<Integer> children = nodes.get(n).ch;
            if (children.isEmpty()) {
                System.out.println("- " + nodes.get(n).sub);
                return;
            }
            System.out.println("┐ " + nodes.get(n).sub);
            for (int i = 0; i < children.size() - 1; i++) {
                Integer c = children.get(i);
                System.out.print(pre + "├─");
                visualize_f(c, pre + "│ ");
            }
            System.out.print(pre + "└─");
            visualize_f(children.get(children.size() - 1), pre + "  ");
        }
    }

    public static void main(String[] args) {
        new SuffixTree("banana$").visualize();
    }
}