static public Automaton concatenate(List<Automaton> l){
  Automaton result=new Automaton();
  for (  Automaton a : l) {
    if (a.getNumStates() == 0) {
      result.finishState();
      return result;
    }
    int numStates=a.getNumStates();
    for (int s=0; s < numStates; s++) {
      result.createState();
    }
  }
  int stateOffset=0;
  Transition t=new Transition();
  for (int i=0; i < l.size(); i++) {
    Automaton a=l.get(i);
    int numStates=a.getNumStates();
    Automaton nextA=(i == l.size() - 1) ? null : l.get(i + 1);
    for (int s=0; s < numStates; s++) {
      int numTransitions=a.initTransition(s,t);
      for (int j=0; j < numTransitions; j++) {
        a.getNextTransition(t);
        result.addTransition(stateOffset + s,stateOffset + t.dest,t.min,t.max);
      }
      if (a.isAccept(s)) {
        Automaton followA=nextA;
        int followOffset=stateOffset;
        int upto=i + 1;
        while (true) {
          if (followA != null) {
            numTransitions=followA.initTransition(0,t);
            for (int j=0; j < numTransitions; j++) {
              followA.getNextTransition(t);
              result.addTransition(stateOffset + s,followOffset + numStates + t.dest,t.min,t.max);
            }
            if (followA.isAccept(0)) {
              followOffset+=followA.getNumStates();
              followA=(upto == l.size() - 1) ? null : l.get(upto + 1);
              upto++;
            }
 else {
              break;
            }
          }
 else {
            result.setAccept(stateOffset + s,true);
            break;
          }
        }
      }
    }
    stateOffset+=numStates;
  }
  if (result.getNumStates() == 0) {
    result.createState();
  }
  result.finishState();
  return result;
}

static public Automaton concatenate ( List < Automaton > l ) { Automaton result = new Automaton ( ) ; for ( Automaton a : l ) { if ( a . getNumStates ( ) == 0 ) { result . finishState ( ) ; return result ; } int numStates = a . getNumStates ( ) ; for ( int s = 0 ; s < numStates ; s ++ ) { result . createState ( ) ; } } int stateOffset = 0 ; Transition t = new Transition ( ) ; for ( int i = 0 ; i < l . size ( ) ; i ++ ) { Automaton a = l . get ( i ) ; int numStates = a . getNumStates ( ) ; Automaton nextA = ( i == l . size ( ) - 1 ) ? null : l . get ( i + 1 ) ; for ( int s = 0 ; s < numStates ; s ++ ) { int numTransitions = a . initTransition ( s , t ) ; for ( int j = 0 ; j < numTransitions ; j ++ ) { a . getNextTransition ( t ) ; result . addTransition ( stateOffset + s , stateOffset + t . dest , t . min , t . max ) ; } if ( a . isAccept ( s ) ) { Automaton followA = nextA ; int followOffset = stateOffset ; int upto = i + 1 ; while ( true ) { if ( followA != null ) { numTransitions = followA . initTransition ( 0 , t ) ; for ( int j = 0 ; j < numTransitions ; j ++ ) { followA . getNextTransition ( t ) ; result . addTransition ( stateOffset + s , followOffset + numStates + t . dest , t . min , t . max ) ; } if ( followA . isAccept ( 0 ) ) { followOffset += followA . getNumStates ( ) ; followA = ( upto == l . size ( ) - 1 ) ? null : l . get ( upto + 1 ) ; upto ++ ; } else { break ; } } else { result . setAccept ( stateOffset + s , true ) ; break ; } } } } stateOffset += numStates ; } if ( result . getNumStates ( ) == 0 ) { result . createState ( ) ; } result . finishState ( ) ; return result ; }
returns an automaton that accepts the concatenation of the languages of the given automata . < p > complexity : linear in total number of states .
