题意:有若干个由小写字母组成的名字,对于每个名字,只取它的最短前缀,使得这些取出来的前缀互不相同,输出原名及取出的前缀(2 <= 名字个数 <= 1000, 1 <= 每个名字的长度 <= 20)。
题目链接:http://poj.org/problem?id=2001
——>>又一道前缀树Trip题目呀~
设cnt[i]为第i个结点有多少个名字经过,那么,若cnt[i]为1,则表明只有1个名字经过,下面只表示1个人,输出每个前缀时到此停止;若cnt[i] > 1,则表明不止1个名字经过,必须往下扫描,直到能分辨出来为止。
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 1000 + 10;
const int maxw = 20 + 5;
char name[maxn][maxw];
int n;
struct node{
int cnt;
node *next[26];
node(){
cnt = 0;
memset(next, 0, sizeof(next));
}
};
struct Trip{
node *root;
Trip(){
root = new node;
}
int idx(char c){
return c - 'a';
}
void insert(char *s){
int len = strlen(s), i;
node *t = root;
for(i = 0; i < len; i++){
int c = idx(s[i]);
if(!t->next[c]) t->next[c] = new node;
t->next[c]->cnt++;
t = t->next[c];
}
}
void solve(){
int i, j, c;
for(i = 0; i < n; i++){
printf("%s ", name[i]);
node *t = root;
int len = strlen(name[i]);
for(j = 0; j < len; j++){
c = idx(name[i][j]);
putchar(name[i][j]);
if(t->next[c]->cnt == 1) break;
t = t->next[c];
}
putchar('\n');
}
}
};
int main()
{
n = 0;
Trip trip;
while(scanf("%s", name[n]) == 1) trip.insert(name[n++]);
trip.solve();
return 0;
}