/// <summary>
            /// Stores built automaton in pre-allocated <see cref="Automaton{TSequence,TElement,TElementDistribution,TSequenceManipulator,TThis}"/> object.
            /// </summary>
            public DataContainer GetData(bool?isDeterminized = null)
            {
                if (this.StartStateIndex < 0 || this.StartStateIndex >= this.states.Count)
                {
                    throw new InvalidOperationException(
                              $"Built automaton must have a valid start state. " +
                              $"StartStateIndex = {this.StartStateIndex}, states.Count = {this.states.Count}");
                }

                var hasEpsilonTransitions     = false;
                var usesGroups                = false;
                var hasOnlyForwardTransitions = true;

                var resultStates              = ReadOnlyArray.CreateBuilder <StateData>(this.states.Count);
                var resultTransitions         = ReadOnlyArray.CreateBuilder <Transition>(this.transitions.Count - this.numRemovedTransitions);
                var nextResultTransitionIndex = 0;

                for (var i = 0; i < resultStates.Count; ++i)
                {
                    var firstResultTransitionIndex = nextResultTransitionIndex;
                    var transitionIndex            = this.states[i].FirstTransitionIndex;
                    while (transitionIndex != -1)
                    {
                        var node       = this.transitions[transitionIndex];
                        var transition = node.Transition;
                        Debug.Assert(
                            transition.DestinationStateIndex < resultStates.Count,
                            "Destination indexes must be in valid range");
                        resultTransitions[nextResultTransitionIndex] = transition;
                        ++nextResultTransitionIndex;
                        hasEpsilonTransitions = hasEpsilonTransitions || transition.IsEpsilon;
                        usesGroups            = usesGroups || (transition.Group != 0);

                        if (transition.DestinationStateIndex <= i)
                        {
                            hasOnlyForwardTransitions = false;
                        }

                        transitionIndex = node.Next;
                    }

                    resultStates[i] = new StateData(
                        firstResultTransitionIndex,
                        nextResultTransitionIndex - firstResultTransitionIndex,
                        this.states[i].EndWeight);
                }

                Debug.Assert(
                    nextResultTransitionIndex == resultTransitions.Count,
                    "number of copied transitions must match result array size");

                // Detect two very common automata shapes
                var isEnumerable = hasOnlyForwardTransitions ? true : (bool?)null;

                return(new DataContainer(
                           this.StartStateIndex,
                           resultStates.MoveToImmutable(),
                           resultTransitions.MoveToImmutable(),
                           !hasEpsilonTransitions,
                           usesGroups,
                           isDeterminized,
                           isZero: null,
                           isEnumerable: isEnumerable));
            }