Pagini recente » Cod sursa (job #145725) | Istoria paginii monthly-2012/runda-2/solutii | Arhiva de probleme | Cod sursa (job #1298809) | Cod sursa (job #2221837)
#include <iostream>
#include <assert.h>
#include <fstream>
#include <string>
#include <sstream>
using namespace std;
template<typename counterType>
struct NodeTypeCatalog
{
struct TrieNodeBasic
{
counterType count,prefixCount;
TrieNodeBasic* child[26];
TrieNodeBasic* parent;
typedef counterType type;
TrieNodeBasic()
{
char* _begin = (char*)(this);
_memset( _begin, _begin + sizeof(*this) );
}
TrieNodeBasic* push(const char c)
{
const char cc = c - 'a';
if( this->child[cc] == 0 )
{
this->child[cc] = new TrieNodeBasic();
this->child[cc]->parent = this;
}
this->child[cc]->prefixCount++;
return this->child[cc];
}
TrieNodeBasic* next(const char c){
if( !(c >= 'a' && c <= 'z') )
return 0;
const char cc = c - 'a';
if( this->child[cc] == 0 )
return 0;
return this->child[cc];
}
void clean(const TrieNodeBasic* head, const string &word){
if( this->prefixCount != 1 )
return;
TrieNodeBasic* current = this;
uint64_t index = 0;
while( current != head && current->prefixCount == 1)
{
++index;
TrieNodeBasic* toBeDeleted = current;
current = current->parent;
delete toBeDeleted;
}
index = word.size() - index;
current->child[ word[index] -'a' ] = 0;
while( current != head )
{
current->prefixCount--;
current = current->parent;
}
}
};
private:
void static _memset(char* _begin, const char *_end)
{
assert( _begin < _end ); //invalid call
while( _begin < _end )
{
*_begin = 0;
++_begin;
}
}
};
template<class NodeType>
class Trie{
public:
Trie(){
this->head = new NodeType();
}
void pushWord(const string& word)
{
NodeType* current = this->head;
for( char c : word)
{
current = current->push(c);
assert(c != 0);
}
current->count++;
}
void popWord(string word){
NodeType* current = this->head;
for( char c : word)
{
current = current->next(c);
if( current == 0 )
return ;
}
if( current->count >= 1 ){
current->count--;
}
current->clean(this->head, word);
}
typename NodeType::type
countWord(const string& word)
{
NodeType* current = this->head;
for( char c : word)
{
current = current->next(c);
if( current == 0 )
return 0;
}
return current->count;
}
uint64_t prefix(const string& word)
{
NodeType* current = this->head;
uint64_t length = 0;
for( char c : word)
{
current = current->next(c);
if( current == 0 )
{
break;
}
++length;
}
return length ;
}
private:
NodeType* head;
};
int main()
{
ios_base::sync_with_stdio(false);
Trie<NodeTypeCatalog<unsigned>::TrieNodeBasic> trie;
const string inputFileName = "trie.in";
const string outputFileName = "trie.out";
ifstream input(inputFileName , std::ifstream::in);
ofstream output(outputFileName, std::ofstream::out);
while( input.good() )
{
int _case = -1;
string word;
input >> _case >> word;
if( _case == -1 )
{
break;
}
switch (_case)
{
case 0:
trie.pushWord(word);
break;
case 1:
trie.popWord(word);
break;
case 2:
output << (int)trie.countWord(word) << '\n';
break;
case 3:
output << trie.prefix(word) << '\n';
break;
default:
output << "Invalid operation\n";
}
}
return 0;
}