Pagini recente » Cod sursa (job #402937) | Cod sursa (job #810803) | Cod sursa (job #1515185) | Cod sursa (job #2742039) | Cod sursa (job #2222641)
#include <iostream>
#include <assert.h>
#include <fstream>
#include <string>
#include <sstream>
using namespace std;
/*
to do:
if it can be deleted -> traverse from head to leaf ( delete parent?? )
check https://infoarena.ro/job_detail/1666508?action=view-source
*/
template<typename counterType>
struct NodeTypeCatalog{
struct TrieNodeBasic{
counterType wordCount,prefixCount;
TrieNodeBasic* child[26];
TrieNodeBasic* parent;
typedef counterType size_t;
TrieNodeBasic() {
char* _begin = (char*)(this);
_memset( _begin, _begin + sizeof(TrieNodeBasic) );
}
TrieNodeBasic(TrieNodeBasic* parent) {
char* _begin = (char*)(this);
_memset( _begin, _begin + sizeof(TrieNodeBasic) );
this->parent = parent;
}
TrieNodeBasic* push(char c){
if( ! this->valid(c)){
return nullptr;
}
c = position( repair(c) );
if( this->child[c] == nullptr ){
this->child[c] = new TrieNodeBasic(this);
}
this->child[c]->markPrefix();
return this->child[c];
}
TrieNodeBasic* next(char c){
if( ! this->valid(c)){
return nullptr;
}
return this->child[ position( repair(c) ) ];
}
void clean(const TrieNodeBasic* head, const string &word){
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->unmark();
current = current->parent;
}
}
void forget(char c){
if( ! this->valid(c)){
return;
}
this->child[ position( repair(c) ) ] = nullptr;
}
void markWord(){
++wordCount;
}
void unmarkWord(){
--wordCount;
}
void markPrefix(){
++prefixCount;
}
void unmarkPrefix(){
--prefixCount;
}
counterType countWord(){
return wordCount;
}
counterType countPrefix(){
return prefixCount;
}
private:
bool valid(const char key){
return ( key >= 'a' && key <= 'z' );
}
char repair(const char c){
return c; //to be modified in derived classes
}
char position(const char c){
return c - 'a';
}
};
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){
assert( current = current->push(c) );
}
current->markWord();
}
int32_t popWord(const string& word){
if( countWord(word) > 0 ){
return unmarkWord(word);
}
else{
return -1;
}
}
int32_t unmarkWord(const string& word){
NodeType* current = this->head;
NodeType* older = this->head;
bool toDelete = false;
for( char c : word){
switch( toDelete ){
case false:
assert( current = current->next(c) );
current->unmarkPrefix();
if( current->countPrefix() == 0 ){
toDelete = true;
older->forget(c);
}
break;
case true:
delete older;
assert( current = current->next(c) );
break;
default:
assert( false );
}
older = current;
}
if( toDelete && older != this->head ){
delete older;
}else{
current->unmarkWord();
}
return 0;
}
typename NodeType::size_t
countWord(const string& word)
{
NodeType* current = this->head;
for( char c : word)
{
current = current->next(c);
if( current == nullptr )
{
return 0;
}
}
return current->countWord();
}
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;
}