Cod sursa(job #1736707)

Utilizator retrogradLucian Bicsi retrograd Data 2 august 2016 14:46:22
Problema Aho-Corasick Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 2.6 kb
#include <bits/stdc++.h>

using namespace std;

struct AhoCorasick {
 
    struct Node {
        int link;
        map<char, int> leg;
    };
    vector<Node> T;
    int root = 0, nodes = 1;

    AhoCorasick(int sz) {
        T.resize(sz);
    }

    // Adds a word to trie and returns the end node
    int AddWord(const string &word) {
        int node = root;
        for(auto c : word) {

            auto &nxt = T[node].leg[c];

            if(nxt == 0) 
                nxt = nodes++;

            node = nxt;
        }
     
        return node;
    }

    // Advances from a node with a character (like an automaton)
    int Advance(int node, char chr) {
        while(node != -1 && T[node].leg.count(chr) == 0)
            node = T[node].link;
        
        if(node == -1)
            return root;
        
        return T[node].leg[chr];
    }

    // Builds links
    void BuildLinks() {
        
        queue<int> Q;
        Q.push(root);
        T[root].link = -1;
        
        while(!Q.empty()) {
            int node = Q.front();
            Q.pop();

            for(auto &p : T[node].leg) {
                int vec = p.second;
                char chr = p.first;

                T[vec].link = Advance(T[node].link, chr);
                Q.push(vec);
            }
        }
    }
};
AhoCorasick aho(1000005);

vector<int> occurences;
void SolveFor(string text) {
    occurences.resize(aho.nodes);
    
    int node = aho.root;
    for(auto c : text) {
        node = aho.Advance(node, c);
        occurences[node] += 1;
    }

    vector<int> degree(aho.nodes);
    for(int node = 1; node < aho.nodes; ++node) {
        degree[aho.T[node].link] += 1;
    }
    
    queue<int> Q;
    for(int node = 0; node < aho.nodes; ++node) {
        if(degree[node] == 0)
            Q.push(node);
    }

    while(!Q.empty()) {
        int node = Q.front();
        int link = aho.T[node].link;
        Q.pop();
        
        if(link == -1) continue;

        occurences[link] += occurences[node];
        if(--degree[link] == 0) {
            Q.push(link);
        }
    }
}

int main() {
    freopen("ahocorasick.in", "r", stdin);
    freopen("ahocorasick.out", "w", stdout);

    string text, word;
    cin >> text;

    int n;
    cin >> n;

    vector<int> endNode(n);
    for(int i = 0; i < n; ++i) {
        cin >> word;
        endNode[i] = aho.AddWord(word);
    }

    aho.BuildLinks();

    SolveFor(text);
    for(int i = 0; i < n; ++i)
        cout << occurences[endNode[i]] << "\n";



    return 0;
}