Cod sursa(job #3351206)

Utilizator TheRomulusIvan Remus TheRomulus Data 17 aprilie 2026 15:29:33
Problema Trie Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 7.04 kb
#include <iostream>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <limits.h>
#include <chrono>
#include <numeric>
#include <iomanip>

#include <vector>
#include <string>
#include <set>
#include <unordered_set>
#include <map>
#include <unordered_map>
#include <bitset>
#include <deque>  
#include <stack>
#include <queue>
#include <list>
#include <string.h>

using namespace std;

#include <ext/pb_ds/assoc_container.hpp>

using namespace __gnu_pbds;

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<string, string> pss;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<pii> vii;
typedef vector<pll> vll;
typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef vector<bool> vb;
typedef vector<vb> vvb;

template <class T>
using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
 
double EPS = 1e-9;
int INF = 1000000005;
long long INFF = 1000000000000000005LL;
double PI = acos(-1);

#define M 1000000007

#define rall(x) (x).rbegin(), (x).rend()
#define all(x) (x).begin(), (x).end()

// auto lim=unique(all(v));
// v.resize(distance(v.begin(), lim));

struct custom_hash {
    static uint64_t splitmix64(uint64_t x) {
        // http://xorshift.di.unimi.it/splitmix64.c
        x += 0x9e3779b97f4a7c15;
        x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
        x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
        return x ^ (x >> 31);
    }

    size_t operator()(uint64_t x) const {
        static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();
        return splitmix64(x + FIXED_RANDOM);
    }
};

struct pair_custom_hash {
    static uint64_t splitmix64(uint64_t x) {
        // http://xorshift.di.unimi.it/splitmix64.c
        x += 0x9e3779b97f4a7c15;
        x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
        x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
        return x ^ (x >> 31);
    }

    template <class T1, class T2>
    size_t operator()(const pair<T1, T2>& p) const
    {
        static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();

        auto hash1 = splitmix64(p.first+FIXED_RANDOM);
        auto hash2 = splitmix64(p.second+FIXED_RANDOM);
 
        return hash1^hash2;
    }
};

ll gcd(ll a,ll b){
    ll r;
    while(b){
        r=a%b;
        a=b;
        b=r;
    }
    return a;
}

ll lcm(ll a,ll b){
    return a*b/gcd(a,b);
}

template<class T> T nxt() {
    T x;
    cin >> x;
    return x;
}

class TrieNode{
    public:
    TrieNode* children[26];
    int noWords;

    TrieNode(){
        noWords=0;
        memset( children, 0, sizeof( children ) );
    }
};

void insertWord(TrieNode* root,const string& word){
    TrieNode* currentNode=root;
    for(auto character:word){
        int position=character-'a';
        if(currentNode->children[position]==nullptr){
            // Create a new node
            currentNode->children[position]=new TrieNode();
        }

        currentNode=(currentNode->children[position]);
    }

    currentNode->noWords++;
}

int getCountOfWord(TrieNode* root,const string& word){
    TrieNode* currentNode=root;
    for(char character:word){
        int position=character-'a';
        
        // If no node in the direction of this word,it doesn't exists and its count is 0
        if(currentNode->children[position]==nullptr){
            return 0;
        }
        currentNode=currentNode->children[position];
    }

    return currentNode->noWords;
}

int getLongestCommonPrefixLength(TrieNode* root,const string& word){
    TrieNode* currentNode=root;
    int n=word.size();
    for(int i=0;i<n;++i){
        int position=word[i]-'a';
        if(currentNode->children[position]==nullptr){
            return i;
        }
        currentNode=currentNode->children[position];
    }

    return word.size();
}

int countChildren(TrieNode* node){
    // Count number of children of node that are not null  
    int count=26;
    for(int i=0;i<26;++i){
        count-=(node->children[i]==nullptr);
    }
    return count;
}

void deleteWord(TrieNode* root,const string& word){
    TrieNode* currentNode=root;
    if(!getCountOfWord(root,word)){
        return;
    }

    int n=word.size();
    int startPos=0;
    stack<TrieNode*> path;
    path.push(currentNode);
    for(int i=0;i<n;++i){
        int position=word[i]-'a';
        currentNode=currentNode->children[position];
        if(i<n-1&&(currentNode->noWords||countChildren(currentNode)>1)){
            startPos=i+1;
        }

        path.push(currentNode);
    }

    currentNode->noWords--;
    if(!currentNode->noWords&&!countChildren(currentNode)){
        for(int i=n-1;i>=startPos;--i){
            // Delete an empty node
            delete path.top();
            path.pop();

            TrieNode* node=path.top();
            
            int position=word[i]-'a';
            node->children[position]=nullptr;
        }
    }
}

bool deleteWordRec(TrieNode* root,TrieNode* node,const string& word,int k){
    if(k==int(word.size())){
        node->noWords--;
    }
    else{
        int position=word[k]-'a';
        bool deletedChildren=deleteWordRec(root,node->children[position],word,k+1);
        if(deletedChildren){
            node->children[position]=nullptr;
        }
    }

    if(!node->noWords&&!countChildren(node)&&node!=root){
        delete node;
        return 1;
    }
    return 0;
}

void SolveConsole(){
    int n;
    cin>>n;
    TrieNode* root=new TrieNode();
    for(int i=0;i<n;++i){
        int t;
        string w;
        cin>>t>>w;

        if(t==0){
            insertWord(root,w);
        }
        else if(t==1){
            deleteWordRec(root,root,w,0);
        }
        else if(t==2){
            cout<<getCountOfWord(root,w)<<'\n';
        }
        else if(t==3){
            cout<<getLongestCommonPrefixLength(root,w)<<'\n';
        }
        else{
            exit(1);
        }
    }
}

void SolveFile(string fileName){
    int n;
    cin>>n;
    TrieNode* root=new TrieNode();

    std::ifstream instream(fileName+".in");
    string lineText;
    while(getline(instream,lineText)){
        int t=lineText[0]-'0';
        string w=lineText.substr(2,30);

        if(t==0){
            insertWord(root,w);
        }
        else if(t==1){
            deleteWord(root,w);
            // deleteWord2(root,w);
        }
        else if(t==2){
            cout<<getCountOfWord(root,w)<<'\n';
        }
        else if(t==3){
            cout<<getLongestCommonPrefixLength(root,w)<<'\n';
        }
        else{
            exit(1);
        }
    }
}

int main(){
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);

    freopen("trie.in", "r", stdin);
    freopen("trie.out", "w", stdout);
    SolveFile("trie");

    // SolveConsole();

    return 0;
}