题目意思:头哥,众所周知,作为acm队的主力选手,最近遇到了一些烦恼,那就是CET-4临近了,但是他还有很多单词没记住.
现在头哥有n个单词没记住,(所有的单词长度加起来不超过5e5),他需要区分其中的m对单词,因为两个单词前面有一部分是一样的,所以他只需要记住后面不相等的部分,所以头哥想要知道每对单词最长相等的前缀长度。
题目连接:
http://202.118.31.226/problem/720
思路就是,建个字典树在,所为的最长公共前缀,可以这样求,即是,两个字符串的最近公共祖先LCA 的那个字母的深度。
需要注意一下的是。我在自己的电脑上 结构体里开了个26*100000的数组,就运行错误了,交到oj 能AC ;
#include<stdio.h>
#include<algorithm>
#include<string>
#include<string.h>
using namespace std;
const int maxnode=5*100000;
int f[maxnode];
int V=-1;
struct Trie
{
int ch[maxnode][26];
int val[maxnode];
int sz;
Trie() { sz=1; memset(ch[0],0,sizeof(ch[0]));}
int idx(char c) {return c-'a';}
void insert(char *s,int v,int num)
{
int u=0, n=strlen(s);
for(int i=0;i<n;i++)
{
int c=idx(s[i]);
if(!ch[u][c])
{
memset(ch[sz],0,sizeof(ch[sz]));
val[sz]=0;
ch[u][c]=sz++;
}
u=ch[u][c];
}
val[u]=v;
f[num]=u;
V=max(V,u);
}
};
char ss[100000*5+10];
int parent[32][100000*5+10];
int depth[100000*5+10];
void dfs(int v,int p,int d,Trie &t1)
{
parent[0][v]=p;
depth[v]=d;
for(int i=0;i<26;i++)
{
if(t1.ch[v][i]!=0)
{
dfs(t1.ch[v][i],v,d+1,t1);
}
}
}
void init(int V)
{
for(int k=0;k+1<32;k++)
{
for(int v=0;v<=V;v++)
{
if(parent[k][v]<0) { parent[k+1][v]=-1;
}else {
parent[k+1][v]=parent[k][parent[k][v]];
}
}
}
}
int lca(int u,int v)
{ // printf("look %d %d %d %d\n",u,v,depth[u],depth[v]);
if(depth[u]>depth[v])
swap(u,v);
for(int k=0;k<32;k++)
{
if((depth[v]-depth[u])>>k&1){
// printf("depv%d depu%d %d %d\n",v,u,depth[v]-depth[u],parent[k][v]);
v=parent[k][v];
}
}
if(u==v) return u;
for(int k=32-1;k>=0;k--)
{
if(parent[k][u]!=parent[k][v])
{
u=parent[k][u];
v=parent[k][v];
}
}
return parent[0][u];
}
int main()
{
//freopen("F:\\123.txt","r",stdin);
int t,m,n;
scanf("%d",&t);
V=-1;
for(int ik=1;ik<=t;ik++)
{
printf("Case #%d:\n",ik);
//memset(parent,0,sizeof(parent));
//memset(depth,0,sizeof(depth));
Trie t1;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%s",ss);
t1.insert(ss,1,i);
}
dfs(0,-1,0,t1);
init(V);
int u,v,pot;
for(int i=0;i<m;i++)
{
scanf("%d%d",&u,&v);
pot=lca(f[u],f[v]);
printf("%d\n",depth[pot]);
}
}
return 0;
}
/* int query(char *s)
{
int u=0,n=strlen(s);
for(int i=0;i<n;i++)
{
int c=idx(s[i]);
if(!ch[u][c])
{
return -1;
}else
{
u=ch[u][c];
}
}
return 1&&val[u];
} */