Cod sursa(job #2295070)

Utilizator sorina.aldeaAldea Sorina-Theodora sorina.aldea Data 3 decembrie 2018 01:42:40
Problema Aho-Corasick Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.23 kb
using namespace std;

#include <iostream>
#include <cstring>
#include <string>
#include <vector>
#include <queue>
#include <map>
#include <iterator>
 
#define foreach(x, v) for (typeof (v).begin() x=(v).begin(); x !=(v).end(); ++x)
#define For(i, a, b) for (int i=(a); i<(b); ++i)
#define D(x) cout << #x " is " << x << endl
 
const int MAXS = 1000000; // Max number of states in the matching machine.
// Should be equal to the sum of the length of all keywords.
 
const int MAXC = 10000; // Number of characters in the alphabet.
 
int out[MAXS]; // Output for each state, as a bitwise mask.
int f[MAXS]; // Failure function
int g[MAXS][MAXC]; // Goto function, or -1 if fail.
 
int buildMatchingMachine(const vector<string> &words, char lowestChar = 'a',
        char highestChar = 'z') {
    memset(out, 0, sizeof out);
    memset(f, -1, sizeof f);
    memset(g, -1, sizeof g);
    int states = 1; // Initially, we just have the 0 state
    
    for (int i = 0; i < words.size(); ++i) {
        const string &keyword = words[i];
        int currentState = 0;
        
        for (int j = 0; j < keyword.size(); ++j) {
            int c = keyword[j] - lowestChar;
            if (g[currentState][c] == -1) { 
                // Allocate a new node
                g[currentState][c] = states++;
            }
            currentState = g[currentState][c];
        }

        out[currentState] |= (1 << i); // There's a match of keywords[i] at node currentState.
    }
    // State 0 should have an outgoing edge for all characters.
    for (int c = 0; c < MAXC; ++c) {
        if (g[0][c] == -1) {
            g[0][c] = 0;
        }
    }
 
    // Now, let's build the failure function
    queue<int> q;
    
    for (int c = 0; c <= highestChar - lowestChar; ++c) { 
        // Iterate over every possible input
        // All nodes s of depth 1 have f[s] = 0
        if (g[0][c] != -1 and g[0][c] != 0) {
            f[g[0][c]] = 0;
            q.push(g[0][c]);
        }
    }

    while (q.size()) {
        int state = q.front();
        q.pop();
        
        for (int c = 0; c <= highestChar - lowestChar; ++c) {
            if (g[state][c] != -1) {
                int failure = f[state];
                
                while (g[failure][c] == -1) {
                    failure = f[failure];
                }
                
                failure = g[failure][c];
                f[g[state][c]] = failure;
                out[g[state][c]] |= out[failure]; // Merge out values
                
                q.push(g[state][c]);
            }
        }
    }
 
    return states;
}

int findNextState(int currentState, char nextInput, char lowestChar = 'a') {
    int answer = currentState;
    int c = nextInput - lowestChar;
    
    while (g[answer][c] == -1) {
        answer = f[answer];
    }
    
    return g[answer][c];
}

map<string, int> searchWords(vector<string> keywords, string text) {
    map<string, int> m;

    buildMatchingMachine(keywords, 'a', 'z');
    int currentState = 0;
    
    for (int i = 0; i < text.size(); ++i) {
        currentState = findNextState(currentState, text[i], 'a');
        
        if (out[currentState] == 0) {
            continue; // Nothing new, let's move on to the next character.
        }
        
        for (int j = 0; j < keywords.size(); ++j) {
            if (out[currentState] & (1 << j)) { 
                // Matched keywords[j]
                cout << keywords[j] << endl;
                
                if (m.find(keywords[j]) == m.end()) {
                    m.insert(make_pair(keywords[j], 1));
                } else {
                    if (m.find(keywords[j]) != m.end()) {
                        int value = m.find(keywords[j])->second;
                        value++;
                        m[keywords[j]] = value;
                    }
                }

            }
        }
    }

    return m;
}

 
int main() {
    string text;
    vector<string> keywords;

    cin >> text;

    int imax;
    cin >> imax;

    for (int i = 0; i < imax; i++) {
        string s;
        cin >> s;
        keywords.push_back(s);
    }

    map<string, int> final = searchWords(keywords, text);

    for (int i = 0; i < imax; i++) {
        int x = final.find(keywords[i])->second;
        cout << x << endl;
    }

    
    return 0;
}