POJ2001Shortest Prefixes(字典树)

题目大意就是帮你给N条字符串,每条长度不超过20。问要将他们单一识别出来,每个字符串最短可以缩为多短。

如:

abc

abcdefg

bc

adef

这四个字符串就可分别缩写为

abc

abcd

b

ad

方法:   字典树(可以参阅http://s.acmore.net/show_article/show/58)。

另外我还用了一个bool数组last用来记录每个单一识别的字符串最短可以到哪个位置,他的下标就是字典树中每个字母对应的序号

方法如下:(以上面的为例)

当输入的字符串在某一个位置开始与之前的不同,就记录这个不同的字母(设置为true),之后的不再改变

当输入字符串的某位置在建好的树中时,把last加长(设置为true)

第一次输入:abc          last[0]=true;

第二次输入:abcdefg    last[0]=last[1]=last[2]=last[3]=true;

第三次输入:bc            last[0]=true;

第四次输入:adef         last[0]=last[1]=true;

这样一来输出端长度就分别为1、4、1、2

代码实现如下:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <iostream>
 5 #include <stack>
 6 #include <set>
 7 #include <queue>
 8 #define MAX(a,b) (a) > (b)? (a):(b)
 9 #define MIN(a,b) (a) < (b)? (a):(b)
10 #define mem(a) memset(a,0,sizeof(a))
11 #define INF 1000000007
12 #define MAXN 20005
13 using namespace std;
14 
15 int trie[MAXN][26],val[MAXN],S;
16 bool last[MAXN];
17 char ma[1005][30];
18 
19 int get_num(char ch){return ch-'a';}
20 
21 void init()
22 {
23     mem(trie);mem(val);
24     mem(last);mem(ma);
25     S = 1;
26 }
27 
28 void insert(char *s)
29 {
30     int u=0,len = strlen(s);
31     int flag = 1;
32     for(int i=0;i<len;i++)
33     {
34         int c = get_num(s[i]);
35         if(!trie[u][c])
36         {
37             trie[u][c] = S;
38             val[u] = 1;
39             if(flag)//如果与上面的字符串开始不一样,酒吧第一个开始不一样的位置设置为true
40             {
41                 last[u]=true;
42                 flag = 0;//之后的依然是false
43             }
44             u = S;
45             S++;
46         }
47         else if(val[u] == 1)
48         {
49             u = trie[u][c];
50             last[u] = true;//在查找中发现与已建好的树里面相同的数,那么需要识别的字符串就要相应的加长
51         }
52     }
53     if(val[u]==1 || val[u] == 2)return;
54     else val[u] = 2;
55 }
56 
57 int main()
58 {
59     init();
60     int T =0;
61     while(scanf("%s",ma[T])!=EOF)
62     {
63         insert(ma[T++]);
64     }
65     for(int i=0;i<T;i++)
66     {
67         printf("%s ",ma[i]);
68         int u=0,j=0;
69         while(last[u] && ma[i][j])
70         {
71             printf("%c",ma[i][j]);
72             u = trie[u][get_num(ma[i][j++])];
73         }
74         printf("\n");
75     }
76     return 0;
77 }

 

posted @ 2013-07-06 18:51  再见~雨泉  阅读(264)  评论(0编辑  收藏  举报