题目链接:http://poj.org/problem?id=2001
题意:给n个单词,对于每个单词求出一个前缀,这个前缀不能是其他单词的前缀,只能用来唯一表示这个单词,而且使得前缀长度最短。
思路:建一棵trie树,对于每个字母节点都进行计数。那么对于一个单词求最短唯一前缀,只需从每个单词开头字母开始去访问这棵树,在第一个计数节点为1的地方停止输出即可。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
using namespace std;
#define rep(i,j,k) for(int i = j; i <= k; i++ )
#define Rrep(i,j,k) for(int i = j; i >= k; i-- )
#define Clean(x,y) memset(x,y,sizeof(x))
const int maxn = 30;
char str[1100][maxn];
struct trie
{
trie *next[maxn];
int num;
};
void init( trie *x )
{
x->num = 0;
rep(i,0,maxn-1) x->next[i] = NULL;
}
void insert( trie *x , char s[] )
{
trie *temp = x;
int k = 0;
while(s[k])
{
int index = s[k] - 'a';
if ( temp->next[index] == NULL )
{
temp->next[index] = new trie;
init( temp->next[index] );
}
temp = temp->next[index];
temp->num++;
k++;
}
}
void out( trie *x , char s[] )
{
trie *temp = x;
int k = 0;
while( s[k] )
{
int index = s[k] - 'a';
temp = temp->next[index];
putchar(s[k]);
if ( temp->num == 1 ) break;
k++;
}
}
trie *root = new trie;
int main()
{
init(root);
int s = 0;
while( gets(str[++s]) )
{
insert(root,str[s]);
}
rep(i,1,s)
{
printf("%s ",str[i]);
out(root,str[i]);
putchar('\n');
}
return 0;
}