Cod sursa(job #1765949)

Utilizator theodor.moroianuTheodor Moroianu theodor.moroianu Data 27 septembrie 2016 10:18:30
Problema Aho-Corasick Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.12 kb
#include <fstream>
#include <vector>
#include <string>
#include <queue>
#include <cstring>
#include <cstdlib>
#define f(a) ((a) - 'a')
using namespace std;

typedef struct Aho * Arbore;
const int SIGMA = 27;

struct Aho
{
	Arbore fail, fii[SIGMA];
	int match;
	vector <int> dict;
	inline Aho()
	{
		memset(fii, 0x00, sizeof(fii));
		match = 0;
		fail = 0;
	}
};


void add(string &a, int cuv, Arbore k);
vector <Arbore> make_fail(Arbore k);
void autom(Arbore k, string &a);
vector <int> make_calc(Arbore k, vector <Arbore> &bfs, int s);

int main()
{
	ifstream in("ahocorasick.in");
	ofstream out("ahocorasick.out");
	string a, b;
	int n;
	Arbore R = new Aho();
	in >> a >> n;
	for (int i = 0; i < n; i++) {
		in >> b;
		add(b, i, R);
	}

	R->fail = R;
	vector <Arbore> bfs = make_fail(R);
	autom(R, a);
	vector <int> rez = make_calc(R, bfs, n);

	for (auto i : rez)
		out << i << '\n';

	return 0;
}

void add(string & a, int cuv, Arbore k)
{
	for (const char &c : a) {
		if (!k->fii[f(c)])
			k->fii[f(c)] = new Aho();
		k = k->fii[f(c)];
	}
	k->dict.push_back(cuv);
}

vector<Arbore> make_fail(Arbore k)
{
	Arbore tmp, a;
	vector <Arbore> bfs;
	queue <Arbore> q;
	q.push(k);
	bfs.push_back(k);

	while (!q.empty()) {
		a = q.front();
		q.pop();

		for (int i = 0; i < SIGMA; i++) {
			if (a->fii[i]) {

				for (tmp = a->fail; tmp != k && !tmp->fii[i]; tmp = tmp->fail);

				if (tmp->fii[i] && tmp != a)
					tmp = tmp->fii[i];

				a->fii[i]->fail = tmp;

				q.push(a->fii[i]);
				bfs.push_back(a->fii[i]);
			}
		}
	}

	return bfs;
}

void autom(Arbore k, string & a)
{
	Arbore act = k;
	for (const char &c: a) {
		while (act != k && !act->fii[f(c)])
			act = act->fail;

		if (act->fii[f(c)]) {
			act = act->fii[f(c)];
			act->match++;
		}
	}
}

vector<int> make_calc(Arbore k, vector<Arbore>& bfs, int s)
{
	vector <int> rez(s, 0);
	for (reverse_iterator <vector <Arbore>::iterator> it = bfs.rbegin(); it != bfs.rend(); it++) {
		for (int x : (*it)->dict)
			rez[x] += (*it)->match;

		(*it)->fail->match += (*it)->match;
	}
	return rez;
}