题目链接:http://uoj.ac/contest/2/problem/13
题解:
考虑这个路径非常像一个trie,我们维护一个trie,再维护一个
g
o
[
i
]
go[i]
go[i]表示trie上
i
i
i这个点下一步应该跳到
g
o
[
i
]
go[i]
go[i](真实路径),其余都是trie基本操作,感觉这个思路还是很妙的(我感觉我想到了2333)
PS:
一开始想写个30pts暴力结果交上去直接60pts 23333
代码:
// by Balloons
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define mpr make_pair
#define debug() puts("okkkkkkkk")
#define rep(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
using namespace std;
typedef long long LL;
const int inf = 1 << 30;
int n,m;
char s[500005];
int tr[500005][27],fa[500005],go[500005];
// tr[now][j] 表示 trie 上 now 这个点经过j这条边到达的点
char cur[500005];
// cur[i] 代表 trie上 i 这个点的字符
int tot=0;
char ans[500005];
int update(){
scanf("%s",s);
int len=strlen(s),now=0;
if(s[len-1]!='/')s[len]='/';else --len;
for(int i=0;i<=len;i++){
int j=s[i]-'a';
if(s[i]=='/')j=26;
if(j==26)now=go[now];
if(i==len)continue;
if(tr[now][j]==-1){ // 新开一个结点
tr[now][j]=++tot;
cur[tr[now][j]]=s[i];
go[tot]=tot;
fa[tot]=now;
}
now=tr[now][j];
}
return now;
}
int main(){
memset(tr,-1,sizeof tr);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
int fx=update(),fy=update();
go[fx]=fy;
}
for(int i=1;i<=m;i++){
int ff=update(),len=0;
for(int j=ff;j;j=fa[j])ans[++len]=cur[j];
if(len==0)ans[++len]='/';
for(int j=len;j>=1;j--)printf("%c",ans[j]);
puts("");
}
return 0;
}