Cod sursa(job #1252369)

Utilizator okros_alexandruOkros Alexandru okros_alexandru Data 30 octombrie 2014 18:11:35
Problema Aho-Corasick Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.77 kb
#include <fstream>
#include <vector>
#include <queue>

#define Cmax 26
#define Wmax 10100
#define Smax 1000100
#define ord(x) (x - 'a')
#define nextNode node->Son[ord(*pointer)]
#define nextSon node->Son[i]
#define pb push_back

using namespace std;

int N;
char A[Smax];

struct Node {

    int listIndex;
    Node * Son[Cmax], * Fail;

    Node() {

        listIndex = 0;

        for(int i = 0; i < Cmax; i++)
            Son[i] = 0;

        }
    };

class Dictionary {

    private:
        Node * Root;
        int nList, visited[Smax];
        vector <int> List[Smax];
        queue <Node * > Queue;

    public:
        int Count[Wmax];

    public:

        Dictionary() {

            Root = new Node;

        }

        void insert(char * pointer) {

            Node * node = Root;

            while(*pointer) {

                if(nextNode == 0)
                    nextNode = new Node;

                node = nextNode;
                pointer++;

                }

            ++nList;

            if(node->listIndex == 0)
                node->listIndex = nList,
                List[nList].pb(nList);
            else
                List[node->listIndex].pb(nList);

            }

        void computeFail() {

            int i;
            Node * node = Root, * p;

            for(i = 0; i < Cmax; i++)
                if(nextSon != 0) {
                    nextSon->Fail = Root;
                    Queue.push(nextSon);
                    }

            while(!Queue.empty()) {

                node = Queue.front();
                Queue.pop();

                for(i = 0; i < Cmax; i++)
                    if(nextSon != 0) {

                        for(p = node; p != Root; p = p->Fail)
                            if(p->Fail->Son[i] != 0) {
                                nextSon->Fail = p->Fail->Son[i];
                                break;
                                }

                        if(nextSon->Fail == 0)
                            nextSon->Fail = Root;

                        Queue.push(nextSon);

                        if(nextSon->Fail->listIndex != 0) {

                            if(nextSon->listIndex == 0)
                                nextSon->listIndex = ++nList;

                            List[nextSon->listIndex].insert(List[nextSon->listIndex].end(), List[nextSon->Fail->listIndex].begin(), List[nextSon->Fail->listIndex].end());

                            }

                    }

                }

        }

        int search(char * pointer) {

            int i, j;
            Node * node = Root;

            for(; *pointer; pointer++) {

                while(node != Root && nextNode == 0)
                    node = node->Fail;

                if(nextNode != 0)
                    node = nextNode;

                if(node->listIndex != 0)
                    visited[node->listIndex]++;

                }

            for(i = 1; i <= nList; i++)
                if(visited[i] != 0)
                    for(j = 0; j < List[i].size(); j++)
                        Count[List[i][j]] += visited[i];

            }

} D;

void Solve() {

    D.computeFail();
    D.search(A + 1);

}
void Read() {

    char Word[Wmax];
    ifstream in("ahocorasick.in");

    in.getline(A + 1, Smax);
    in >> N;
    in.getline(Word + 1, Wmax);

    for(int i = 1; i <= N; i++) {

        in.getline(Word + 1, Wmax);
        D.insert(Word + 1);

        }

    in.close();

}
void Write() {

    ofstream out("ahocorasick.out");

    for(int i = 1; i <= N; i++)
        out << D.Count[i] << '\n';

    out.close();

}
int main() {

    Read();
    Solve();
    Write();

    return 0;

}