/*
 * ExactMultiNondeterministicSubsequenceAutomaton.h
 *
 *  Created on: 7. 4. 2015
 *      Author: Jan Travnicek
 */

#ifndef _EXACT_MULTI_NONDETERMINISTIC_SUBSEQUENCE_AUTOMATON__H_
#define _EXACT_MULTI_NONDETERMINISTIC_SUBSEQUENCE_AUTOMATON__H_

#include <automaton/FSM/EpsilonNFA.h>
#include <string/LinearString.h>

#include <alib/pair>

namespace stringology {

namespace indexing {

class ExactMultiNondeterministicSubsequenceAutomaton {
public:
	/**
	 * Performs conversion.
	 * @return left regular grammar equivalent to source automaton.
	 */
	template < class SymbolType >
	static automaton::EpsilonNFA < SymbolType, ext::pair < unsigned, unsigned > > construct ( const ext::set < string::LinearString < SymbolType > > & texts);
};

template < class SymbolType >
automaton::EpsilonNFA < SymbolType, ext::pair < unsigned, unsigned > > ExactMultiNondeterministicSubsequenceAutomaton::construct ( const ext::set < string::LinearString < SymbolType > > & texts) {
	automaton::EpsilonNFA < SymbolType, ext::pair < unsigned, unsigned > > res ( ext::make_pair ( 0u, 0u ) );
	res.addFinalState ( ext::make_pair ( 0u, 0u ) );

	unsigned j = 1;
	for ( const string::LinearString < SymbolType > & text : texts ) {
		res.addInputSymbols ( text.getAlphabet ( ) );

		res.addState ( ext::make_pair ( 0u, j ) );
		res.addFinalState ( ext::make_pair ( 0u, j ) );
		res.addTransition ( ext::make_pair ( 0u, 0u ), ext::make_pair ( 0u, j ) );

		unsigned i = 1;
		for ( const SymbolType & symbol : text.getContent ( ) ) {
			res.addState ( ext::make_pair ( i, j ) );
			res.addFinalState ( ext::make_pair ( i, j ) );

			res.addTransition ( ext::make_pair ( i - 1, j ), symbol, ext::make_pair ( i, j ) );
			res.addTransition ( ext::make_pair ( i - 1, j ), ext::make_pair ( i, j ) );
			i++;
		}
		j++;
	}

	return res;
}

} /* namespace indexing */

} /* namespace stringology */

#endif /* _EXACT_MULTI_NONDETERMINISTIC_SUBSEQUENCE_AUTOMATON__H_ */
