Cod sursa(job #2420631)

Utilizator Kln1000Ciobanu Bogdan Kln1000 Data 12 mai 2019 21:01:02
Problema Trie Scor 70
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.64 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <string>

using namespace std;

#pragma pack(1)

class trie{
public:
    trie() {
        for (auto &i : root.sons)
            i = nullptr;
        root.parent = nullptr;
    }

    void add(std::string target) {
        node *crawler = this -> begin();

        for (auto letter : target) {
            if (crawler -> sons[normalize(letter)] == nullptr)
                ++(crawler -> forks),
                crawler -> sons[normalize(letter)] = new node(1 + crawler -> level, normalize(letter)),
                crawler -> sons[normalize(letter)] -> parent = crawler;

            crawler = crawler -> sons[normalize(letter)];
        }

        if (crawler -> occurences++ == 0)
            crawler -> end_of_word = true;
    }

    void remove(std::string target) {
        node *crawler = this -> begin();

        for (auto letter : target) {
            if (crawler -> sons[normalize(letter)] == nullptr)
                return;
            crawler = crawler -> sons[normalize(letter)];
        }

        if (--crawler -> occurences == 0) {
            crawler -> end_of_word = false;
            node *next;

            while (crawler -> forks == 0 && !crawler -> end_of_word && crawler != this -> begin()) {
                next = crawler -> parent;
                --next -> forks;
                next -> sons[crawler -> index] = nullptr;
                delete crawler;
                crawler = next;
            }
        }
    }

    int get_occurences(std::string target) {
        node *crawler = this -> begin();

        for (auto letter : target) {
            if (crawler -> sons[normalize(letter)] == nullptr)
                return 0;
            crawler = crawler -> sons[normalize(letter)];
        }

        return crawler -> occurences;
    }

    int get_closest_match_length(std::string target) {
        node *crawler = this -> begin();
        int retval = 0;

        for (auto letter : target) {
            if (crawler -> sons[normalize(letter)] == nullptr)
                return retval;
            ++retval;
            crawler = crawler -> sons[normalize(letter)];
        }

        return retval;
    }

    ~trie() {
        for (auto i : root.sons)
            if (i != nullptr)
                clean_node(i);
    }

private:
    static const int start_of_alphabet = 'a';
    static const int size_of_alphabet = 26;

    int normalize(const char &target) {
        return target - start_of_alphabet;
    }

    struct node{
        node *sons[size_of_alphabet] = {};
        node *parent;
        int occurences, forks, level, index;
        bool end_of_word;
        node (int _level = 0, int letter = 0) {
            index = letter;
            level = _level;
        }
    } root;

    node * begin() {
        return &root;
    }

    void clean_node(node *target) {
        for (auto i : target -> sons)
            if (i != nullptr)
                clean_node(i);

        delete target;
    }
};

ifstream fin ("trie.in");
ofstream fout ("trie.out");

int main()
{
    int query;
    string str;
    trie h;

    while (fin >> query) {
        fin >> str;
        switch(query) {
        case 0:{
            h.add(str);
            break;
        }
        case 1:{
            h.remove(str);
            break;
        }
        case 2:{
            fout << h.get_occurences(str) << "\n";
            break;
        }
        case 3:{
            fout << h.get_closest_match_length(str) << "\n";
            break;
        }
        }
    }
    return 0;
}