public static long number_of_different_substrings(char[] s)
        {
            SuffixAutomaton sa = SuffixAutomaton.Build(s);

            if (!sa.sortedTopologically)
            {
                sa.SortTopologically();
            }
            long[] D = new long[sa.gen];
            for (int i = sa.gen - 1; i >= 0; i--)
            {
                D[i] = 1;
                for (int j = 0; j < sa.nodes[i].np; j++)
                {
                    D[i] += D[sa.nodes[i].next[j].id];
                }
            }
            return(D[0] - 1);
        }
        public static char[] least_cyclic_shift(char[] s)
        {
            char[] ss = new char[s.Length * 2];
            Buffer.BlockCopy(s, 0, ss, 0, sizeof(char) * s.Length);
            Buffer.BlockCopy(s, 0, ss, sizeof(char) * s.Length, sizeof(char) * s.Length);
            SuffixAutomaton sa = SuffixAutomaton.Build(ss);

            if (!sa.lexsorted)
            {
                sa.LexSort();
            }
            SuffixAutomaton.Node v = sa.t0;
            char[] a  = new char[s.Length];
            int    ix = 0;

            while (ix < s.Length)
            {
                v       = v.next[0];
                a[ix++] = v.key;
            }
            return(a);
        }