code: func unionN(l []*Automaton) *Automaton {
  	ans := newEmptyAutomaton()
  	// create initial state
  	ans.createState()
  	// copy over all automata
  	for _, a := range l {
  		ans.copy(a)
  	}
  	// add epsilon transition from new initial state
  	stateOffset := 1
  	for _, a := range l {
  		if a.numStates() == 0 {
  			continue
  		}
  		ans.addEpsilon(0, stateOffset)
  		stateOffset += a.numStates()
  	}
  	ans.finishState()
  	return removeDeadStates(ans)
  }
docs: /*
  Returns an automaton that accepts the union of the languages of the
  given automata.
  
  Complexity: linear in number of states.
  */