Cod sursa(job #1160700)

Utilizator dariusdariusMarian Darius dariusdarius Data 30 martie 2014 18:40:02
Problema Trie Scor 5
Compilator cpp Status done
Runda Arhiva educationala Marime 3.4 kb
#include <algorithm>
#include <fstream>
#include <vector>
using namespace std;

string word;

struct Trie {
    int sons[26]; //indicii fiilor prin fiecare litera
    int parent; //indicele tatalui
    int count; //numarul de aparitii ale cuvantului curent in dictionar
    int weight; //numarul de cuvinte din subarbore
    Trie() {
        for(int i = 0; i < 26; ++ i) {
            sons[i] = -1;
        }
        parent = -1;
        weight = count = 0;
    }
    Trie(int father) {
        for(int i = 0; i < 26; ++ i) {
            sons[i] = -1;
        }
        parent = father;
        weight = count = 0;
    }
};
vector<Trie> trie;
vector<int> stack;

void insert() {
    int node = 0; //nodul curent, initial in radacina (0)
    for(int pos = 0; pos < static_cast<int>(word.size()); ++ pos) {
        ++ trie[node].weight;
        if(trie[node].sons[word[pos] - 'a'] == -1) {
            //trebuie sa adaugam un nod in trie
            if(stack.empty()) { //nu exista nici o casuta goala
                trie.push_back(Trie(node));
                trie[node].sons[word[pos] - 'a'] = static_cast<int>(trie.size()) - 1;
            } else { //exista un loc gol, nu merita sa alocam altceva
                trie[stack.back()] = Trie(node);
                trie[node].sons[word[pos] - 'a'] = stack.back();
                stack.pop_back();
            }
        }
        node = trie[node].sons[word[pos] - 'a'];
    }
    ++ trie[node].weight;
    ++ trie[node].count;
}

void erase(int node, const string :: iterator &it, const string :: iterator &end) {
    if(it == end) {
        -- trie[node].count;
        -- trie[node].weight;
        if(node /* sa nu cumva sa stergem radacina */ && trie[node].weight == 0) {
            trie[trie[node].parent].sons[*(it - 1) - 'a'] = -1; //nu mai este fiul nimanui, nu mai exista!
            stack.push_back(node); //casuta nodului curent devine goala, o adaugam in stiva
        }
        return;
    }
    erase(trie[node].sons[*it - 'a'], it + 1, end); //trebuie facut recursiv, ca la iesirea din recursivitate sa vedem 
                                                    //daca stergem fizic si nodul curent
    -- trie[node].weight;
    if(node && trie[node].weight == 0) {
        trie[trie[node].parent].sons[*(it - 1) - 'a'] = -1;
        stack.push_back(node);
    }
}

int get_to() {
    int node = 0, pos = 0;
    while(pos < static_cast<int>(word.size()) && node != -1) {
        node = trie[node].sons[word[pos] - 'a'];
        ++ pos;
    }
    return node;
}
int query() {
    int node = 0, pos = 0;
    while(pos < static_cast<int>(word.size()) && node != -1) {
        node = trie[node].sons[word[pos] - 'a'];
        ++ pos;
    }
    return pos - 1;
}

int main() {
    ifstream fin("trie.in");
    ofstream fout("trie.out");
    int op;
    trie.push_back(Trie());
    //stiva memoreaza pozitiile din Trie care sunt goale, deci in care pot aloca noduri
    //mereu o sa fie in stiva trie.size(), deoarece mereu este o varianta sa dau pur si simplu push_back
    while(fin >> op >> word) {
        if(op == 0) {
            insert();
        } else if(op == 1) {
            erase(0, word.begin(), word.end());
        } else if(op == 2) {
            int node = get_to();
            if(node != -1) {
                fout << trie[node].count << "\n";
            } else {
                fout << "0\n";
            }
        } else {
            fout << query() << "\n";
        }
    }
    return 0;
}