/*
 * SuffixTrieFactors.h
 *
 *  Created on: 2. 1. 2017
 *      Author: Jan Travnicek
 */

#ifndef SUFFIX_TRIE_FACTORS_H_
#define SUFFIX_TRIE_FACTORS_H_

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

namespace stringology {

namespace query {

/**
 * Query suffix trie for given string.
 *
 * Source: ??
 */

class SuffixTrieFactors {
	template < class SymbolType >
	static void accumulateResult ( const ext::trie < SymbolType, ext::optional < unsigned > > & trie, ext::set < unsigned > & res ) {
		if ( trie.getData ( ) )
			res.insert ( trie.getData ( ).value ( ) );

		for ( const std::pair < const SymbolType, ext::trie < SymbolType, ext::optional < unsigned > > > & child : trie.getChildren ( ) ) {
			accumulateResult ( child.second, res );
		}
	}

public:
	/**
	 * Query a suffix trie
	 * @param suffix trie to query
	 * @param string string to query by
	 * @return occurences of factors
	 */
	template < class SymbolType >
	static ext::set < unsigned > query ( const indexes::stringology::SuffixTrie < SymbolType > & suffixTrie, const string::LinearString < SymbolType > & string );

};

template < class SymbolType >
ext::set < unsigned > SuffixTrieFactors::query ( const indexes::stringology::SuffixTrie < SymbolType > & suffixTrie, const string::LinearString < SymbolType > & string ) {
	const ext::trie < SymbolType, ext::optional < unsigned > > * node = & suffixTrie.getRoot ( );
	for ( const SymbolType & symbol : string.getContent ( ) ) {
		auto iter = node->getChildren ( ).find ( symbol );
		if ( iter == node->getChildren ( ).end ( ) ) {
			return {};
		}
		node = & iter->second;
	}

	ext::set < unsigned > res;
	accumulateResult ( * node, res );
	return res;
}

} /* namespace query */

} /* namespace stringology */

#endif /* SUFFIX_TRIE_FACTORS_H_ */
