/* * Author: Radovan Cerveny */ #pragma once #include <limits> #include <indexes/stringology/FactorOracleAutomaton.h> #include <string/LinearString.h> namespace stringology { namespace indexing { class ExactFactorOracleAutomaton { private: static constexpr unsigned infinity = std::numeric_limits < unsigned >::max ( ); template < class SymbolType > static void oracleAddLetter ( automaton::DFA < SymbolType, unsigned > & oracle, const SymbolType & symbol, ext::map < unsigned, unsigned > & supplyFunction ); public: /** * Constructs factor oracle automaton for given pattern. * @return factor oracle automaton for given pattern */ template < class SymbolType > static indexes::stringology::FactorOracleAutomaton < SymbolType > construct ( const string::LinearString < SymbolType > & pattern ); }; template < class SymbolType > indexes::stringology::FactorOracleAutomaton < SymbolType > ExactFactorOracleAutomaton::construct ( const string::LinearString < SymbolType > & pattern ) { automaton::DFA < SymbolType, unsigned > oracleAutomaton ( 0u ); oracleAutomaton.addFinalState ( oracleAutomaton.getInitialState ( ) ); ext::vector < unsigned > supplyFunction { infinity }; //vector is fine, the state number is exactly the index to the vector oracleAutomaton.setInputAlphabet ( pattern.getAlphabet ( ) ); for ( const SymbolType & symbol : pattern.getContent ( ) ) oracleAddLetter ( oracleAutomaton, symbol, supplyFunction ); return indexes::stringology::FactorOracleAutomaton < SymbolType > ( std::move ( oracleAutomaton ) ); } template < class SymbolType > void ExactFactorOracleAutomaton::oracleAddLetter ( automaton::DFA < SymbolType, unsigned > & oracle, const SymbolType & symbol, ext::map < unsigned, unsigned > & supplyFunction ) { unsigned lastState = oracle.getStates ( ).size ( ) - 1; unsigned newState = lastState + 1; oracle.addState ( newState ); oracle.addFinalState ( newState ); oracle.addTransition ( lastState, symbol, newState ); unsigned kState = supplyFunction.find( lastState )->second; while ( kState != infinity && oracle.getTransitions ( ).find ( { kState, symbol } ) == oracle.getTransitions ( ).end ( ) ) { oracle.addTransition ( kState, symbol, newState ); kState = supplyFunction.find( kState )->second; } unsigned supplyState = 0; if ( kState != infinity ) supplyState = oracle.getTransitions ( ).find( { kState, symbol } )->second; supplyFunction.insert( { newState, supplyState } ); } } /* namespace indexing */ } /* namespace stringology */