#include <algorithm>
#include <iterator>
#include <map>
#include <memory>
#include <utility>
template<class T, typename U>
class trie
{
public:
trie() : _root(_data) {}
typedef typename std::map<T, U>::iterator iterator;
typedef typename std::map<T, U>::reverse_iterator reverse_iterator;
iterator begin()
{
return _data.begin();
}
iterator end()
{
return _data.end();
}
reverse_iterator rbegin()
{
return _data.rbegin();
}
reverse_iterator rend()
{
return _data.rend();
}
inline void erase(const T &key)
{
_root.erase(key.begin(), key.end());
}
inline iterator find(const T &key)
{
return _root.find(key.begin(), key.end());
}
inline std::pair<iterator, bool> insert(const T &key, const U &value)
{
auto t = _data.insert(std::pair<T, U>(key, value));
_root.insert(key.begin(), key.end(), t.first);
return t;
}
protected:
class subtrie
{
public:
subtrie(std::map<T, U> &data) : _data(data) {}
inline void erase(const T &key)
{
erase(key.begin(), key.end());
}
void erase(typename T::const_iterator begin, typename T::const_iterator end)
{
typename std::map<typename T::const_iterator::value_type, subtrie>::iterator t = _subtries.find(*begin);
begin++;
if(begin != end)
t->second.erase(begin, end);
else
_subtries.erase(t);
}
inline iterator find(const T &key)
{
return find(key.begin(), key.end());
}
iterator find(typename T::const_iterator begin, typename T::const_iterator end)
{
if(begin != end)
{
typename std::map<typename T::const_iterator::value_type, subtrie>::iterator t = _subtries.find(*begin);
if(t != _subtries.end())
{
begin++;
return t->second.find(begin, end);
}
else
return _data.end();
}
else
return _it;
}
inline void insert(iterator it)
{
insert(it->first.begin(), it->first.end(), it);
}
void insert(typename T::const_iterator begin, typename T::const_iterator end, const iterator it)
{
if(begin != end)
{
typename std::map<typename T::const_iterator::value_type, subtrie>::iterator t = _subtries.insert(typename std::map<typename T::const_iterator::value_type, subtrie>::value_type(*begin, subtrie(_data))).first;
begin++;
t->second.insert(begin, end, it);
}
else
_it = it;
}
private:
iterator _it;
std::map<T, U> &_data;
std::map<typename T::const_iterator::value_type, subtrie> _subtries;
};
private:
subtrie _root;
std::map<T, U> _data;
};