diff --git a/alib2algo/src/stringology/properties/BackboneLength.cpp b/alib2algo/src/stringology/properties/BackboneLength.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f1f9f2d3dea3d566ffae906bdacddaa3c0e5f886 --- /dev/null +++ b/alib2algo/src/stringology/properties/BackboneLength.cpp @@ -0,0 +1,22 @@ +/* + * BackboneLength.cpp + * + * Created on: 17. 5. 2017 + * Author: Jan Travnicek + */ + +#include "BackboneLength.h" + +namespace stringology { + +namespace properties { + +unsigned BackboneLength::length ( const automaton::Automaton & automaton ) { + return dispatch ( automaton.getData ( ) ); +} + +auto backboneLengthDFA = BackboneLength::RegistratorWrapper < unsigned, automaton::DFA < > > ( BackboneLength::length ); + +} /* namespace properties */ + +} /* namespace stringology */ diff --git a/alib2algo/src/stringology/properties/BackboneLength.h b/alib2algo/src/stringology/properties/BackboneLength.h new file mode 100644 index 0000000000000000000000000000000000000000..d11b0cdb312d851ccf03b73c3aa5981cd1c71d50 --- /dev/null +++ b/alib2algo/src/stringology/properties/BackboneLength.h @@ -0,0 +1,75 @@ +/* + * BackboneLength.h + * + * Created on: 17. 5. 2017 + * Author: Jan Travnicek + */ + +#ifndef BACKBONE_LENGTH_H +#define BACKBONE_LENGTH_H + +#include <automaton/Automaton.h> +#include <automaton/FSM/DFA.h> +#include <core/multipleDispatch.hpp> +#include <set> +#include <queue> +#include <algorithm> +#include <utility> + +namespace stringology { + +namespace properties { + +class BackboneLength : public std::SingleDispatch < BackboneLength, unsigned, const automaton::AutomatonBase & > { +public: + /** + * Computes length of backbone for a suffix/factor/oracle automaton + * @param automaton the suffix/factor/oracle automaton + * @return backbone length + */ + static unsigned length ( const automaton::Automaton & automaton ); + + template < class SymbolType, class StateType > + static unsigned length ( const automaton::DFA < SymbolType, StateType > & automaton ); + + template < class StateType > + class BackboneLengthLess { + public: + bool operator ( ) ( const std::pair < StateType, unsigned > & first, const std::pair < StateType, unsigned > & second ) { + return first.second < second.second; + } + }; + +}; + +template < class SymbolType, class StateType > +unsigned BackboneLength::length ( const automaton::DFA < SymbolType, StateType > & automaton ) { + std::priority_queue < std::pair < StateType, unsigned >, std::vector < std::pair < StateType, unsigned > >, BackboneLengthLess < StateType > > open; + std::map < StateType, unsigned > closed; + + unsigned max = 0; + open.push ( std::make_pair ( automaton.getInitialState ( ), max ) ); + + while ( ! open.empty ( ) ) { + std::pair < StateType, unsigned > current = std::move ( open.top ( ) ); + open.pop ( ); + unsigned & dist = closed [ current.first ]; + + if ( dist > current.second ) + continue; + + dist = current.second; + max = std::max ( max, current.second ); + + for ( const std::pair < const std::pair < StateType, SymbolType >, StateType > & target : automaton.getTransitionsFromState ( current.first ) ) + open.push ( std::make_pair ( target.second, current.second + 1 ) ); + } + + return max; +} + +} /* namespace properties */ + +} /* namespace stringology */ + +#endif /* BACKBONE_LENGTH_H */