Cod sursa(job #1165146)

Utilizator harababurelPuscas Sergiu harababurel Data 2 aprilie 2014 15:07:22
Problema Trie Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 1.76 kb
#include <iostream>
#include <fstream>
#include <cstring>
#include <cmath>
#define sigma 26
#define nmax 10005
#define lmax 2005
#define ltotal 200005
#define lgmax 12
#define child nd->son[s[p]-'a']
using namespace std;

int n, m, id, nodes = 0, op;
string s;

struct Trie {
	int idx;
	Trie *son[sigma];
	Trie() {
		idx = nodes++; 
		memset(son, 0, sizeof(son));
	}
} *T = new Trie;

Trie *fin[nmax], *sol;
Trie *dp[lgmax][ltotal];
int level[ltotal], lg[lmax];

void add(Trie *nd, int p) {
	if(p == int(s.size())) {
		fin[id] = nd;
		return;
	}

	if(child == NULL) {
		child = new Trie;
		level[child->idx] = level[nd->idx] + 1;

		dp[0][child->idx] = nd;
		for(int j=1; j<lgmax; j++) 
			dp[j][child->idx] = dp[j-1][ dp[j-1][child->idx]->idx ];
	}

	add(nd->son[s[p]-'a'], p+1);
}

Trie *LCA(Trie *a, Trie *b) {
	while(level[a->idx] != level[b->idx]) {
		int delta = abs(level[a->idx] - level[b->idx]);

		if(level[a->idx] > level[b->idx]) a = dp[ lg[delta] ][a->idx]; //a trebuie urcat
		else b = dp[ lg[delta] ][b->idx];
	}
	//acum am a si b pe acelasi nivel
	for(int j=lgmax-1; j>=0; j--)
		if(dp[j][a->idx] != dp[j][b->idx]) {
			a = dp[j][a->idx];
			b = dp[j][b->idx];		
		}
	while(a != b) { a = dp[0][a->idx]; b = dp[0][b->idx]; }
	
	//acum am a si b = LCA
	return a;
}

int main() {
	ifstream f("ratina.in");
	ofstream g("ratina.out");

	for(int i=2; i<lmax; i++) lg[i] = 1 + lg[i/2];

	f>>n>>m;
	f.get();

	for(int j=0; j<lgmax; j++) 
		for(int i=0; i<ltotal; i++)
			dp[j][i] = T;

	for(id=1; id<=n; id++) {
		getline(f, s);
		add(T, 0);
	}
	for(int i=1; i<=m; i++) {
		f>>op;
		
		f>>id; //primul cuvant
		sol = fin[id]; //nodul <ultima-litera> a primului cuvant
		for(int j=2; j<=op; j++) {
			f>>id;
			if(sol != T) sol = LCA(sol, fin[id]);
		}
		g<<level[sol->idx]<<"\n";
	}

	return 0;
}