【UER #1】跳蚤OS(Trie)

跳蚤OS 是跳蚤国自主研发的功能强大的操作系统。

跳蚤OS的文件系统与普通的文件系统类似,是个文件夹套文件夹的结构。文件系统根目录称为“//”。我们可以用文件路径来表明文件所在的位置,比如“/flea/uoj/flea/uoj”表示根目录下的fleaflea文件夹下的uojuoj文件。

跳蚤OS的文件系统中。快捷方式是一种特殊的文件夹,点开该快捷方式相当于打开该快捷方式指向的文件夹。

比如,如果有一个快捷方式 “/etc/abc/etc/abc”,该快捷方式指向 “/flea/def/flea/def”这个文件夹,那么一旦访问“/etc/abc/etc/abc”就相当于访问“/flea/def/flea/def”。

这一天,跳蚤国王正在使用跳蚤OS。初始时文件系统为空,只有根目录。他每次会进行如下操作:

  1. 首先,随便写出两个文件路径 ss 和 tt。
  2. 接着,如果位置 tt 处不存在文件,则在该处创建一个空文件夹。
  3. 最后,跳蚤国王保证 ss 这个位置没有文件,于是在 ss 处创建一个快捷方式指向 tt。如果 tt 是个快捷方式,那么 ss 将指向 tt 所指向的文件夹。

上文所说的“创建”在父级目录不存在的时候要一并创建其父级目录。比如,假设文件系统里只有 “/v/v” 这个文件夹,那么现在我创建 “/v/flea/king/qaq/v/flea/king/qaq” 就会在文件系统中新增三个文件夹:“/v/flea/v/flea”, “/v/flea/king/v/flea/king”, “/v/flea/king/qaq/v/flea/king/qaq”。

跳蚤国王进行了 nn 次这样的操作后,开始不断问他的助手伏特:现在我如果在 pp 这个路径处创建一个文件夹(如果已存在则不创建),那么这个文件夹的真实路径是什么?

于是伏特只好向你求助了,请你帮一帮他吧!请参照样例来更清晰地理解题意。

输入格式

第一行两个正整数n,mn,m,表示跳蚤国王进行了nn个操作,提了mm个问题。

接下来nn行每行两个用空格隔开的字符串s,ts,t,表示跳蚤国王的一次操作。

接下来 mm 行每行一个字符串 pp 表示跳蚤国王的一个询问。

保证所有的 s,t,ps,t,p 都是合法的文件路径。即,文件夹名一定是由小写英文字母组成的非空字符串,路径名一定形如“/xxx/xxx/xxx/.../xxx/xxx/xxx/xxx/.../xxx”这样子。保证当路径不为根目录“//”时,路径不以“//”结尾。

输出格式

对于跳蚤国王的每个询问输出真实路径。

样例一

input

6 5
/root /
/duliu /picks
/vfk /vfleaking
/orz/orz/orz /duliu
/otl /duliu/duliu
/vfk/sb /vfleaking
/vfk/sb/nothing/nothing
/orz
/orz/orz/orz
/qaq
/otl

output

/vfleaking/nothing/nothing
/orz
/picks
/qaq
/picks/duliu

explanation

创建的快捷方式分别为:

  • /root//root→/
  • /duliu/picks/duliu→/picks
  • /vfk/vfleaking/vfk→/vfleaking
  • /orz/orz/orz/picks/orz/orz/orz→/picks
  • /otl/picks/duliu/otl→/picks/duliu
  • /vfleaking/sb/vfleaking/vfleaking/sb→/vfleaking

样例二

input

2 3
/ba/la /
/w/o/w /w
/ba/la/ba/la/ba/la/ba/la/ba/la/ba/la/ba/la
/ba/la/ba/la/ba/la/ba/la/ba/la/ba/la/ba/la/ba
/w/o/w/o/w/o/w/o

output

/
/ba
/w/o

样例三

见样例数据下载

限制与约定

测试点编号nnmm其他
1 200≤200 10≤10 保证单个字符串长度不会超过 4040
2
3
4 20000≤20000 保证每个输入的路径字符串中仅包含一个“//”且位于字符串开头。
保证单个字符串长度不超过1515。
5
6
7 20000≤20000  
8
9
10

对于所有数据,输入中路径字符串总长度不会超过 5×1055×105。

时间限制:1s1s

空间限制:256MB256MB

为了防止有些同学看晕了,我还是再罗嗦几句。下面的路径名都是非法的:

  • /orz//orz/
  • /orz//otl/orz//otl
  • /233/233 (注意,只能含有小写英文字母)

下面的路径名都是合法的:

  • //
  • /orz/otl/oorrzz/oottll/orz/otl/oorrzz/oottll
  • /a

【思路】

       Trie+链接

       给每个节点加个go指针,使之作为快捷方式链接真实路径字符串在 Trie 中对应的结点。

       于是我们可以读入字符串,然后顺着Trie树走。当下一个字符是 “/” 或者已到达字符串结尾时,尝试从 go 指针跳转

【代码】

 1 #include<cmath>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define FOR(a,b,c) for(int a=(b);a<=(c);a++)
 6 using namespace std;
 7 
 8 const int N = 5*1e5+10;
 9 
10 int n,m;
11 char s[N],q[N];
12 
13 struct Trie {
14     int sz; char b[N];
15     int ch[N][27],go[N],fa[N];
16     Trie() { sz=1; }
17     int insert() {
18         int u=1;
19         scanf("%s",s);
20         int len=strlen(s);
21         if(s[len-1]!='/') s[len++]='/';
22         for(int i=0;i<len;i++) {
23             int c=s[i]-'a';
24             if(s[i]=='/') c=26;
25             if(!ch[u][c]) {
26                 ch[u][c]=++sz;
27                 fa[sz]=u;
28                 b[sz]=s[i];
29             }
30             u=ch[u][c];
31             if(s[i]=='/') while(go[u]) u=go[u];
32         }
33         return u;
34     }
35 }T;
36 
37 int main() {
38     scanf("%d%d",&n,&m);
39     for(int i=0;i<n;i++) {
40         int x=T.insert(),y=T.insert();
41         T.go[x]=y;
42     }
43     for(int i=0;i<m;i++) {
44         int x=T.insert();
45         int top=0;
46         for(int i=x;i!=1;i=T.fa[i]) 
47             q[++top]=T.b[i];
48         if(top==1) puts("/");
49         else {
50             while(top>1) printf("%c",q[top--]);
51             puts("");
52         }
53     }
54     return 0;
55 }
原文地址:https://www.cnblogs.com/lidaxin/p/5203542.html