Cod sursa(job #2221850)

Utilizator bogdanpaunFMI Paun Bogdan Gabriel bogdanpaun Data 15 iulie 2018 23:59:19
Problema Trie Scor 65
Compilator cpp Status done
Runda Arhiva educationala Marime 4.52 kb
#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 )
        {
            return;
        }

        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;
}