private static void BuildSuffixAutomaton(char[] x, ref Graph aut) { int i, art, init, last, p, q, r, m = (x.Length - 1); char c; init = Automata.GetInitial(aut); art = Automata.NewVertex(aut); Automata.SetSuffixLink(aut, init, art); last = init; for (i = 0; i < m; ++i) { c = x[i]; p = last; q = Automata.NewVertex(aut); Automata.SetLength(aut, q, Automata.GetLength(aut, p) + 1); Automata.SetPosition(aut, q, Automata.GetPosition(aut, p) + 1); while (p != init && Automata.GetTarget(aut, p, c) == -1) { Automata.SetTarget(aut, p, c, q); Automata.SetShift(aut, p, c, Automata.GetPosition(aut, q) - Automata.GetPosition(aut, p) - 1); p = Automata.GetSuffixLink(aut, p); } if (Automata.GetTarget(aut, p, c) == -1) { Automata.SetTarget(aut, init, c, q); Automata.SetShift(aut, init, c, Automata.GetPosition(aut, q) - Automata.GetPosition(aut, init) - 1); Automata.SetSuffixLink(aut, q, init); } else if (Automata.GetLength(aut, p) + 1 == Automata.GetLength( aut, Automata.GetTarget(aut, p, c))) { Automata.SetSuffixLink(aut, q, Automata.GetTarget(aut, p, c)); } else { r = Automata.NewVertex(aut); Automata.CopyVertex(aut, r, Automata.GetTarget(aut, p, c)); Automata.SetLength(aut, r, Automata.GetLength(aut, p) + 1); Automata.SetSuffixLink(aut, Automata.GetTarget(aut, p, c), r); Automata.SetSuffixLink(aut, q, r); while (p != art && Automata.GetLength(aut, Automata .GetTarget(aut, p, c)) >= Automata.GetLength( aut, r)) { Automata.SetShift(aut, p, c, Automata.GetPosition(aut, Automata.GetTarget(aut, p, c)) - Automata.GetPosition(aut, p) - 1); Automata.SetTarget(aut, p, c, r); p = Automata.GetSuffixLink(aut, p); } } last = q; } Automata.SetTerminal(aut, last); while (last != init) { last = Automata.GetSuffixLink(aut, last); Automata.SetTerminal(aut, last); } }