Cod sursa(job #578632)

Utilizator chibicitiberiuChibici Tiberiu chibicitiberiu Data 11 aprilie 2011 13:57:17
Problema Trie Scor 80
Compilator cpp Status done
Runda Arhiva educationala Marime 3.78 kb
#include <stdio.h>
#include <vector>
#include <stack>
#include <string.h>
using namespace std;

class Node
{
public:
    char Data;
    int IsEnd;
    vector<Node> Children;
    int Depth;

    bool operator== (char c)
    {
        return (Data==c);
    }
    bool operator== (Node c)
    {
        return (Data == c.Data);
    }
    bool operator< (Node c)
    {
        return (Data < c.Data);
    }

    inline Node() { Data = 0; IsEnd=Depth=0; }
    inline Node(char c) { Data = c; IsEnd=Depth=0; }
    inline Node(char c, int end) { Data=c; IsEnd=end; Depth=0;}

    inline Node(char c, int end, int d) { Data=c; IsEnd=end; Depth=d;}

    inline int FindChild(char c)
    {
        for (int i=0; i < Children.size(); i++)
            if (Children[i].Data == c) return i;
        return -1;
    }
};


class Trie
{
    Node root;
public:

    void Insert (char* str)
    {
        int len = strlen(str), i=0;

        // Find last node
        Node* wh = &root;
        int index = 0;

        for (i=0; index != -1 && i < len; i++)
        {
            index = wh->FindChild(str[i]);
            if (index != -1) wh = &(wh->Children[index]);
        }

        if (index == -1)
        {
            for (--i; i < len-1; i++)
            {
                wh->Children.push_back(Node(str[i], 0, wh->Depth+1));
                wh = &(wh->Children[wh->Children.size()-1]);
            }

            wh->Children.push_back(Node(str[len-1], 1, wh->Depth+1));
        }

        else wh->IsEnd++;
    }

    int Count (char* str)
    {
        int len = strlen(str), i=0;

        // Find last node
        Node* wh = &root;
        int index = 0;

        for (i=0; index != -1 && i < len; i++)
        {
            index = wh->FindChild(str[i]);
            if (index != -1) wh = &(wh->Children[index]);
        }

        if (index == -1) return 0;
        return wh->IsEnd;
    }

    void Remove (char* str)
    {
        stack <Node*> s;

        int len = strlen(str), i=0;

        // Find last node
        Node* wh = &root;
        int index = 0;

        for (i=0; index != -1 && i < len; i++)
        {
            s.push(wh);
            index = wh->FindChild(str[i]);
            if (index != -1) wh = &(wh->Children[index]);
        }

        // Make sure word exists
        //if (index == -1 || wh->IsEnd == 0) return;

        // Decrease 1 if there are more words
        if (wh->IsEnd>1 || wh->Children.size() > 0)
            wh->IsEnd--;

        // Remove unused nodes
        else
        {
            int i = len-1;
            while (s.top()->Children.size() < 2 && !s.top()->IsEnd && s.size()>1)
            {
                s.top()->Children.pop_back();
                s.pop(); i--;
            }

            wh = s.top();
            wh->Children.erase(wh->Children.begin() + wh->FindChild(str[i]));

        }
    }

    int LongestCommonPrefix (char* str)
    {
        int len = strlen(str), i=0;

        // Find last node
        Node* wh = &root;
        int index = 0;

        for (i=0; index != -1 && i < len; i++)
        {
            index = wh->FindChild(str[i]);
            if (index != -1) wh = &(wh->Children[index]);
        }

        if (i==wh->Depth && wh->Data == str[i-1]) return i;
        return i-1;
    }

};


int main()
{
    Trie t;

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

    int operation;
    char param[22];

    int count=1;

    while (scanf("%d %s\n", &operation, param) != EOF)
    {
        switch (operation)
        {
            case 0: t.Insert(param);
                break;
            case 1: t.Remove(param);
                break;
            case 2: printf ("%d\n", t.Count(param)); count++;
                break;
            case 3: printf ("%d\n", t.LongestCommonPrefix(param)); count++;
                break;
        }
    }

    return 0;
}