Cod sursa(job #3347876)

Utilizator altomMirel Fanel altom Data 18 martie 2026 17:27:52
Problema Trie Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.97 kb
#include <iostream>
#include <fstream>
#include <vector>
using namespace std;
ifstream fin("trie.in");
ofstream fout("trie.out");

struct trie_node{
    int frec, cnt;
    trie_node* copii[30];

    trie_node() {
        frec=cnt=0;
        for(int i=0;i<30;i++)
            copii[i]=nullptr;
    }
};
trie_node* rad=new trie_node;

inline int idx_of(char c) {
    return c - 'a';
}

void adauga(const string &s) {
    trie_node* nod = rad;
    nod->cnt++; // root counts this insertion
    for (char c : s) {
        int idx = idx_of(c);
        if (idx < 0 || idx >= 26) return; // defensive (shouldn't happen per statement)
        if (nod->copii[idx] == nullptr)
            nod->copii[idx] = new trie_node;
        nod = nod->copii[idx];
        nod->cnt++;
    }
    nod->frec++;
}

void sterge(const string &s) {
    // first walk the path while recording nodes + indices
    trie_node* nod = rad;
    vector<pair<trie_node*, int>> path; // (node, idx used to go to child)
    // decrement root's cnt immediately (we know the word exists by problem statement)
    nod->cnt--;
    for (char c : s) {
        int idx = idx_of(c);
        // defensive checks (should not trigger with valid input)
        if (idx < 0 || idx >= 26) return;
        trie_node* child = nod->copii[idx];
        if (child == nullptr) return; // defensive: word not present (shouldn't happen)
        path.emplace_back(nod, idx);
        nod = child;
        nod->cnt--;
    }
    // nod now points to final node for the word
    if (nod->frec > 0) nod->frec--;
    else return; // defensive: nothing to delete (shouldn't happen)

    // free nodes from leaf upward if they became unused (cnt==0 and frec==0)
    for (int i = (int)path.size() - 1; i >= 0; --i) {
        trie_node* parent = path[i].first;
        int idx = path[i].second;
        trie_node* child = parent->copii[idx];
        if (child && child->cnt == 0 && child->frec == 0) {
            // child subtree is empty: delete node and cut link
            delete child;
            parent->copii[idx] = nullptr;
        } else {
            // if child still has words in subtree, stop deleting upwards
            break;
        }
    }
}

int getCount(string s){
    trie_node* nod=rad;
    for(auto c: s){
        nod=nod->copii[c-'a'];
    }

    return nod->frec;
}

int longestPref(string s){
    trie_node* nod=rad;
    int cnt=0;
    for(auto c: s){
        if(nod->copii[c-'a'] == nullptr){
            break;
        }
        if(nod->copii[c-'a']->cnt==0)
            break;
        nod=nod->copii[c-'a'];
        cnt++;
    }

    return cnt;
}

int main()
{
    int t;
    string s;
    while(fin>>t>>s){
        if(t==0){
            adauga(s);
        }
        if(t==1){
            sterge(s);
        }
        if(t==2){
            cout<<getCount(s)<<'\n';
        }
        if(t==3){
            cout<<longestPref(s)<<'\n';
        }
    }


    return 0;
}