/*
 * SuffixTrieNaive.h
 *
 *  Created on: 1. 11. 2014
 *      Author: Tomas Pecka
 */

#ifndef SUFFIX_TRIE_NAIVE_H_
#define SUFFIX_TRIE_NAIVE_H_

#include <indexes/stringology/SuffixTrie.h>
#include <string/LinearString.h>

namespace stringology {

namespace indexing {

/**
 * Constructs suffix trie for given string.
 *
 * Source: Lectures MI-EVY (CTU in Prague), Year 2014, Lecture 3, slide 4
 */

class SuffixTrieNaive {
public:
	/**
	 * Creates suffix trie
	 * @param string string to construct suffix trie for
	 * @return automaton
	 */
	template < class SymbolType >
	static indexes::stringology::SuffixTrie < SymbolType > construct ( const string::LinearString < SymbolType > & w );

};

template < class SymbolType >
indexes::stringology::SuffixTrie < SymbolType > SuffixTrieNaive::construct ( const string::LinearString < SymbolType > & w ) {
	ext::trie < SymbolType, ext::optional < unsigned > > trie ( ext::optional < unsigned > ( ( unsigned ) w.getContent ( ).size ( ) ) );

	for ( unsigned i = w.getContent ( ).size ( ); i > 0; i-- ) {
		unsigned k = i - 1;
		ext::trie < SymbolType, ext::optional < unsigned > > * n = & trie;

		 // inlined slow_find_one from MI-EVY lectures
		while ( n->getChildren ( ).count ( w.getContent ( )[k] ) )
			n = & n->getChildren ( ).find ( w.getContent ( )[k++] )->second;

		for ( ; k < w.getContent ( ).size ( ); k++ ) {
			ext::optional < unsigned > node = k + 1 < w.getContent ( ).size ( ) ? ext::optional < unsigned > ( ) : ext::optional < unsigned > ( i - 1 );
			n = & n->getChildren ( ).insert ( std::make_pair ( w.getContent ( )[k], ext::trie < SymbolType, ext::optional < unsigned > > ( node ) ) ).first->second;
		}
	}

	return indexes::stringology::SuffixTrie < SymbolType > ( w.getAlphabet ( ), std::move ( trie ) );
}

} /* namespace indexing */

} /* namespace stringology */

#endif /* SUFFIX_TRIE_NAIVE_H_ */
