Trieと 完備辞書はこのために作成しました.
上2つは公開時から不具合修正と機能追加をしています.
LOUDSは, 木構造をビット列で表現します.
節点を幅優先で走査し, 各節点で子の数だけ"1"を並べ, 節点の終端に"0"を置きます.
子のない節点は"0", 子が1つの節点は"10"です.
"add", "and", "ans"からなるトライ木は, LOUDSで表現すると"1011010110000"になります.
ビット列を完備辞書として使用すると,
ビット位置mの子は, $select_{0}(rank_{1}(m))+1$のビット位置から始まります.
また, ビット位置mから始まる節点の節点番号は, $rank_{1}(m)$です.
上図の根は, ビット位置0から始まり, 節点番号は$rank_{1}(0)=0$です.
また, 根は子を1つ持ち, 子は$select_{0}(rank_{1}(0))+1=select_{0}(0)+1=1+1=2$から始まります.
namespace
{
class LOUDS
{
public:
LOUDS();
~LOUDS();
void build(const core::ByteTrie& trie);
const Char* find(const Char* key) const;
private:
LOUDS(const LOUDS&);
LOUDS& operator=(const LOUDS&);
struct TraverseTrie
{
TraverseTrie(LOUDS& louds, const core::ByteTrie& trie)
:louds_(louds)
,trie_(trie)
{}
bool operator()(s32 index, const core::ByteTrie::node_type& node);
LOUDS& louds_;
const core::ByteTrie& trie_;
};
friend struct TraverseTrie;
void clear();
FullyIndexableDictionary fid_;
ArrayPOD<Char> labels_;
ArrayPOD<Char*> values_;
};
bool LOUDS::TraverseTrie::operator()(s32 index, const ByteTrie::node_type& node)
{
const Char* value = trie_.getValue(node);
louds_.labels_.push_back(node.getLabel());
louds_.values_.push_back(NULL);
if(NULL != value){
s32 len = strlen(value);
louds_.values_[index] = (Char*)malloc(sizeof(Char)*(len+1));
memcpy(louds_.values_[index], value, len+1);
}
for(s32 i=0; i<node.getNumChildren(); ++i,++index){
louds_.fid_.add(true);
}
louds_.fid_.add(false);
return true;
}
LOUDS::LOUDS()
{
}
LOUDS::~LOUDS()
{
clear();
}
void LOUDS::build(const core::ByteTrie& trie)
{
clear();
trie.traverse(TraverseTrie(*this, trie));
fid_.build();
}
const Char* LOUDS::find(const Char* key) const
{
assert(NULL != key);
static const u32 Invalid = -1;
u32 bit = 0;
u32 index = 0;
while('\0' != *key){
if(fid_.sizeInBits()<=bit){
return NULL;
}
u32 next=Invalid;
index = fid_.rank_one(bit);
while(0!=fid_.access(bit)){
++index;
if(labels_[index] == *key){
next = bit;
break;
}
++bit;
}
if(Invalid == next){
return NULL;
}
bit = fid_.select_zero(index-1)+1;
++key;
}
return values_[index];
}
void LOUDS::clear()
{
for(s32 i=0; i<values_.size(); ++i){
free(values_[i]);
}
labels_.clear();
values_.clear();
fid_.clear();
}
}

0 件のコメント:
コメントを投稿