Cod sursa(job #1267545)

Utilizator DuxarFII-Stefan-Negrus Duxar Data 20 noiembrie 2014 00:05:05
Problema Aho-Corasick Scor 95
Compilator cpp Status done
Runda Arhiva educationala Marime 2.42 kb
#include <vector>
#include <fstream>
#include <cstdio>
#include <queue>
#include <string>
#include <climits>
#include <iostream>
#include <cassert>

#define pb push_back

using namespace std;

class Node {
public:
	vector <Node*> step;
	vector <int> words;
	Node *fail;
	int endHere;
	
	Node() {
		fail = 0;
		endHere = 0;
		step.resize(26, 0);
	}
	
	void insert(int pos, int lg, string &text, int id) {
		if (pos == lg) {
			words.pb(id);
			return;
		}
		int to = text[pos] - 'a';
		if (step[to] == 0) {
			step[to] = new Node();
		}
		step[to]->insert(pos + 1, lg, text, id);
	}
};

int N;
vector <Node*> que;
Node *rootTrie;
string plaintext;
vector <int> nrWords;

void breadth_first_search(Node *root);
void rev_breadth_first_search();
void solve();

int main() {
#ifdef INFOARENA
	freopen("ahocorasick.in", "r", stdin);
	freopen("ahocorasick.out", "w", stdout);
#else
	freopen("input", "r", stdin);
#endif
	int i;
	string word;
	
	rootTrie = new Node();
	cin >> plaintext;
	cin >> N;
	nrWords.resize(N);
	for (i = 0; i < N; ++i) {
		cin >> word;
		rootTrie->insert(0, (int) word.length(), word, i);
	}
	breadth_first_search(rootTrie);
	solve();
	rev_breadth_first_search();
	
	for (i = 0; i < N; ++i) {
		printf("%d\n", nrWords[i]);
	}
	
	return 0;
}

void solve() {
	int lgText, i, to;
	Node *node = rootTrie;
	lgText = (int) plaintext.length();
	for (i = 0; i < lgText; ++i) {
		to = plaintext[i] - 'a';
		assert(node != 0);
		for (;node != rootTrie && node->step[to] == 0; node = node->fail);
		if (node->step[to] != 0) {
			node = node->step[to];
			assert(node != 0);
			++node->endHere;
		}
	}
}

void rev_breadth_first_search() {
	int i, j;
	Node *node;
	for (i = (int) que.size() - 1; i; --i) {
		node = que[i];
		node->fail->endHere += node->endHere;
		for (j = (int) node->words.size() - 1; j >= 0; --j) {
			nrWords[node->words[j]] += node->endHere;
		}
	}
}

void breadth_first_search(Node *root) {
	int alpha, omega, to;
	Node *toFail, *node;
	root->fail = root;
	
	alpha = omega = 1;
	que.pb(0);
	que.pb(root);
	while(alpha <= omega) {
		node = que[alpha];
		++alpha;
		for (to = 0; to < 26; ++to) {
			if (node->step[to] != 0) {
				for (toFail = node->fail; toFail != root && toFail->step[to] == 0; toFail = toFail->fail);
				if (toFail->step[to] != 0 && toFail->step[to] != node->step[to]) {
					node->step[to]->fail = toFail->step[to];
				}
				else {
					node->step[to]->fail = root;
				}
				++omega;
				que.pb(node->step[to]);
			}
		}
	}
}