Pagini recente » Cod sursa (job #536255) | Cod sursa (job #1994735) | Cod sursa (job #2660302) | Cod sursa (job #901038) | Cod sursa (job #1165146)
#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;
}