POJ 2001 Shortest Prefixes【字典树】

Description

A prefix of a string is a substring starting at the beginning of the given string. The prefixes of "carbon" are: "c", "ca", "car", "carb", "carbo", and "carbon". Note that the empty string is not considered a prefix in this problem, but every non-empty string is considered to be a prefix of itself. In everyday language, we tend to abbreviate words by prefixes. For example, "carbohydrate" is commonly abbreviated by "carb". In this problem, given a set of words, you will find for each word the shortest prefix that uniquely identifies the word it represents.
In the sample input below, "carbohydrate" can be abbreviated to "carboh", but it cannot be abbreviated to "carbo" (or anything shorter) because there are other words in the list that begin with "carbo".
An exact match will override a prefix match. For example, the prefix "car" matches the given word "car" exactly. Therefore, it is understood without ambiguity that "car" is an abbreviation for "car" , not for "carriage" or any of the other words in the list that begins with "car".
Input

The input contains at least two, but no more than 1000 lines. Each line contains one word consisting of 1 to 20 lower case letters.

Output

The output contains the same number of lines as the input. Each line of the output contains the word from the corresponding line of the input, followed by one blank space, and the shortest prefix that uniquely (without ambiguity) identifies this word.

Sample Input

carbohydrate
cart
carburetor
caramel
caribou
carbonic
cartilage
carbon
carriage
carton
car
carbonate

Sample Output

carbohydrate carboh
cart cart
carburetor carbu
caramel cara
caribou cari
carbonic carboni
cartilage carti
carbon carbon
carriage carr
carton carto
car car
carbonate carbona

总结: 算是当作字典树的简单模版。

题意:用一个单词的前缀表示其单词的缩写,要求达到最短而且尽可能不与其他列出的单词产生歧异。
注意:如果一个单词是另外一个的前缀,则其缩写是其本身;否则其缩写绝不能是其他单词的前缀
code:

View Code
#include<stdio.h> 
#include<stdlib.h>
typedef struct Trie
{ //建立字典树
struct Trie *next[26]; //为每个小写字母建立指针
int num; //与当前的前缀字符串相同的的字符串的个数
}Trie,*trie;
trie head;
char s[1010][22];
void init(trie &p) //初始化指针
{
int i;
p=(trie)malloc(sizeof(Trie));
for(i=0;i<26;i++)p->next[i]=NULL;
p->num=0;
}
void update(trie &p,char *a,int k)
{
p->num++; //当前前缀数加1
if(a[k])
{ //如果没有访问到p字符的最后一位,则继续访问;否则返回
trie q;
q=p->next[a[k]-'a'];
if(q==NULL)
{ //如果字符串的下一位从未访问过,则为其开辟空间
init(q);
p->next[a[k]-'a']=q;
}
update(q,a,k+1); //深入字典树的下一层
}
}
int find(trie p,char *a,int k)
{
//通过查看有当前的前缀的单词个数来判断当前单词是否用此前缀
//如果只有当前单词的前缀是当前的前缀字符串或已经访问到当前的末尾,则返回结果
if(p->num==1||!a[k])return k;
//否则继续往下一层深入
return find(p->next[a[k]-'a'],a,k+1);
}
int main()
{
int i,j,n=0,k;
init(head); //初始化头指针
while(~scanf("%s",s[n]))
{
update(head,s[n],0); //插入s[n]
n++;
}
for(i=0;i<n;i++)
{
k=find(head,s[i],0); //查找s[i]的可用前缀
printf("%s ",s[i]);
for(j=0;j<k;j++)
putchar(s[i][j]);
putchar('\n');
}
return 0;
}


posted @ 2012-03-14 18:24  'wind  阅读(255)  评论(0编辑  收藏  举报