Cod sursa(job #1761629)

Utilizator theodor.moroianuTheodor Moroianu theodor.moroianu Data 22 septembrie 2016 17:04:02
Problema Aho-Corasick Scor 5
Compilator cpp Status done
Runda Arhiva educationala Marime 2.06 kb
#include <fstream>
#include <string>
#include <vector>
#include <queue>
#define l(x) (x - 'a')
using namespace std;

typedef class Nod * arbore;

class Nod
{
public:
	char val;
	arbore tata;
	arbore fail;
	vector <int> cuvant; // 0 daca nu e cuvant
	arbore fii[30];
	Nod()
	{
		for (int i = 0; i < 30; i++)
			fii[i] = 0;
	}
};

Nod E;

void adauga(string s, int cuvant);
void creeare_fail(arbore k);
void baga_cuvant(arbore k);
int frc[110];

int main()
{
	ifstream in("ahocorasick.in");
	ofstream out("ahocorasick.out");
	string a, c;
	in >> a;
	int n;
	in >> n;
	for (int i = 1; i <= n; i++) {
		in >> c;
		adauga(c, i);
	}

	E.fail = &E;
	E.val = '$';
	for (int i = 0; i < 30; i++)
		if (E.fii[i] != 0)
			creeare_fail(E.fii[i]);

	baga_cuvant(&E);

	arbore k = &E;
	for (auto i : a) {
		bool modif = 1;
		while (k != &E && k->val != i && k->fii[l(i)] == 0)
			k = k->fail, modif = 0;

		if ((k->val != i || modif) && k->fii[l(i)] != 0)
			k = k->fii[l(i)];
		
		if (k->val == i) {
			for (auto j : k->cuvant)
				frc[j]++;
		}
	}
	for (int i = 1; i <= n; i++)
		out << frc[i] << '\n';

	return 0;
}

void adauga(string s, int cuvant)
{
	arbore k = &E, l;
	for (auto i : s) {
		if (k->fii[l(i)] != 0)
			k = k->fii[l(i)];
		else {
			l = k;
			k->fii[l(i)] = new Nod;
			k = k->fii[l(i)];
			k->val = i;
			k->tata = l;
		}
	}
	k->cuvant.push_back(cuvant);
}

void creeare_fail(arbore k)
{
	k->fail = k->tata->fail;
	while (k->fail->val != '$' && k->fail->fii[l(k->val)] == 0 && k->fail->val != k->val)
		k->fail = k->fail->fail;

	if (k->fail->val != k->val && k->fail->fii[l(k->val)] != 0 && k->tata->val != '$')
		k->fail = k->fail->fii[l(k->val)];

	for (int i = 0; i < 30; i++)
		if (k->fii[i] != 0)
			creeare_fail(k->fii[i]);
}

void baga_cuvant(arbore k)
{
	queue <arbore> q;
	q.push(k);
	while (!q.empty()) {
		k = q.front();
		q.pop();
		for (auto i : k->fail->cuvant)
			k->cuvant.push_back(i);

		for (int i = 0; i < 30; i++)
			if (k->fii[i] != 0)
				q.push(k->fii[i]);
	}
}