Cod sursa(job #1233016)

Utilizator CosminRusuCosmin Rusu CosminRusu Data 24 septembrie 2014 14:52:46
Problema Aho-Corasick Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.59 kb
#include <fstream>
#include <iostream>
#include <vector>
#include <bitset>
#include <string.h>
#include <algorithm>
#include <iomanip>
#include <math.h>
#include <time.h>
#include <stdlib.h>
#include <set>
#include <map>
#include <string>
#include <queue>
#include <deque>

using namespace std;

const char infile[] = "ahocorasick.in";
const char outfile[] = "ahocorasick.out";

ifstream fin(infile);
ofstream fout(outfile);

const int SIGMA = 30;
const int MAXA = 1000005;
const int MAXW = 10005;
const int MAXN = 105;
const int oo = 0x3f3f3f3f;

const inline int min(const int &a, const int &b) { if( a > b ) return b;   return a; }
const inline int max(const int &a, const int &b) { if( a < b ) return b;   return a; }
const inline void Get_min(int &a, const int b)    { if( a > b ) a = b; }
const inline void Get_max(int &a, const int b)    { if( a < b ) a = b; }

class FiniteAutomaton {
private:
    static const int SIGMA = 26;
    static const char START_LETTER = 'a';

    struct Node {
        Node *sons[SIGMA], *pi;
        int matches;
        vector <int> where;
        Node () {
            memset(sons, NULL, sizeof(sons));
            matches = 0;
        }
    };

    Node *Root;
    vector <Node *> Q;
    vector <int> Ans;

    inline int getCode(char s) {
        return s - START_LETTER;
    }
public:
    FiniteAutomaton() {
        Root = new Node();
    }
    inline Node * getRoot() {
        return Root;
    }
    inline void addString(Node *n, char *s, int where) {
        if(!*s) {
            n->where.push_back(where);
            Ans.push_back(0);
            return;
        }
        int son = getCode(*s);
        if(!n->sons[son])
            n->sons[son] = new Node();
        addString(n->sons[son], s + 1, where);
    }
    inline void buildPi() {
        Root->pi = Root;
        Node *K = Root;
        Q.push_back(Root);
        for(int i = 0 ; i < Q.size() ; ++ i) {
            Node *act = Q[i];
            for(int son = 0 ; son < SIGMA ; ++ son)
                if(act->sons[son]) {
                    K = act->pi;
                    while(K != Root && K->sons[son] == NULL)
                        K = K->pi;
                    if(K->sons[son] && K->sons[son] != act->sons[son])
                        K = K->sons[son];
                    act->sons[son]->pi = K;
                    Q.push_back(act->sons[son]);
                }
        }
    }
    inline void AhoCorasick(char *A) {
        int n = strlen(A);
        Node *K = Root;
        for(int i = 0, n = strlen(A) ; i < n ; ++ i) {
            int son = getCode(A[i]);
            while(K != Root && !(K->sons[son]))
                K = K->pi;
            if(K->sons[son])
                K = K->sons[son];
            ++ K->matches;
        }
    }
    inline vector<int> getMatches() {
        for(vector <Node*> :: reverse_iterator it = Q.rbegin(), fin = Q.rend() ; it != fin ; ++ it) {
            if((*it)->pi)
                (*it)->pi->matches += (*it)->matches;
            for(vector <int> :: iterator i = ((*it)->where).begin(), j = ((*it)->where).end(); i != j ; ++ i)
                Ans[*i] = (*it)->matches;
        }
        return Ans;
    }
} Aho;


char A[MAXA], s[MAXW];
int N;


int main() {
    fin >> A >> N;
    for(int i = 0 ; i < N ; ++ i) {
        fin >> s;
        Aho.addString(Aho.getRoot(), s, i);
    }
    Aho.buildPi();
    Aho.AhoCorasick(A);
    vector <int> ans = Aho.getMatches();
    for(auto it : ans)
        fout << it << '\n';
    fin.close();
    fout.close();
    return 0;
}