Cod sursa(job #1964096)

Utilizator SolcanMihaiSolcan Mihai Andrei SolcanMihai Data 13 aprilie 2017 09:19:04
Problema Aho-Corasick Scor 95
Compilator cpp Status done
Runda Arhiva educationala Marime 2.93 kb
#include <cstdio>
#include <queue>
#include <cstring>
#include <unordered_set>

using namespace std;

struct Nod
{
	Nod *fail;
	Nod *vecini[26];
	unordered_set<int> indici;

	Nod()
	{
		fail = NULL;

		for(int i = 0; i < 26; i++)
		{
			vecini[i] = NULL;
		}
	}
};

Nod *root;

const int N = 105;

char sir[1000005];
int n;
char dictionar[N][10005];
int nrAparitii[N];



bool isChar(char x)
{
	if(x >= 'a' && x <= 'z')
	{
		return true;
	}

	return false;
}

bool isDigit(char x)
{
	if(x >= '0' && x <= '9')
	{
		return true;
	}

	return false;
}

char _BUFFER[4096];
int bufferPoz = 4095;

char readCh()
{
	bufferPoz++;

	if(bufferPoz == 4096)
	{
		fread(&_BUFFER[0], sizeof(char), 4096, stdin);
		bufferPoz = 0;
	}

	return _BUFFER[bufferPoz];
}

void citireParsare()
{
	int nr = 0;
	char x = readCh();

	while(isChar(x) == true)	
	{
		sir[nr] = x;
		nr++;
		x = readCh();
	}

	sir[nr] = 0;

	x = readCh();

	while(isDigit(x) == true)	
	{
		n = n * 10 + (x - '0');
		x = readCh();
	}

	x = readCh();

	for(int i = 0; i < n; i++)
	{
		int nr = 0;

		while(isChar(x) == true)	
		{
			dictionar[i][nr] = x;
			nr++;
			x = readCh();
		}

		x = readCh();

		dictionar[i][nr] = 0;
	}
}

void addCuvant(char x[], int nr)
{
	Nod *a = root;	

	int l = strlen(x);

	for(int i = 0; i < l; i++)
	{
		char ch = x[i] - 'a';

		if(a->vecini[ch] == NULL)
		{
			a->vecini[ch] = new Nod();
			a = a->vecini[ch];
		}
		else
		{
			a = a->vecini[ch];
		}
	}

	a->indici.insert(nr);
}

void citire()
{
	scanf("%s\n", &sir);

	scanf("%d", &n);

	for(int i = 0; i < n; i++)
	{
		scanf("%s\n", &dictionar[i]);
	}
}

void construireTrie()
{
	for(int i = 0; i < n; i++)	
	{
		addCuvant(dictionar[i], i);
	}
}

void pregatireAhoCorasick()
{
	queue<Nod*> Q;

	int l = 26;

	for(int i = 0; i < l; i++)
	{
		if(root->vecini[i] != NULL)
		{
			Q.push(root->vecini[i]);
			root->vecini[i]->fail = root;
		}
	}

	while(Q.empty() == false)	
	{
		Nod *r = Q.front();
		Q.pop();
	
		for(int i = 0; i < 26; i++)	
		{
			if(r->vecini[i] != NULL)
			{
				Nod *u = r->vecini[i];
				Nod *v = r->fail;

				Q.push(u);

				while(v->vecini[i] == NULL && v != root)
				{
					v = v->fail;
				}

				if(v->vecini[i] == NULL)
				{
					u->fail = root;
				}
				else
				{
					u->fail = v->vecini[i];
				}

				for(auto y : u->fail->indici)
				{
					u->indici.insert(y);
				}
			}
		}
	}
}

void ahoCorasick()
{
	int l = strlen(sir);
	Nod *q = root;

	for(int i = 0; i < l; i++)
	{
		char ch = sir[i] - 'a';
		
		while(q->vecini[ch] == NULL && q != root)
		{
			q = q->fail;
		}

		if(q == root && q->vecini[ch] == NULL)
		{
			continue;
		}

		q = q->vecini[ch];

		for(auto x : q->indici)
		{
			nrAparitii[x]++;
		}
	}
}

void afisare()
{
	for(int i = 0; i < n; i++)
	{
		printf("%d\n", nrAparitii[i]);
	}
}

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

	root = new Nod();
	citireParsare();
	construireTrie();
	pregatireAhoCorasick();
	ahoCorasick();
	afisare();

	return 0;
}