最短字首(字典樹)------------Five-菜鳥級
最短字首
時限:1000 MS 記憶體限制:30萬K 提交材料共計:21820 接受: 9346
描述
字串的字首是從給定字串的開頭開始的子字串。“碳”的字首是:“c”、“ca”、“car”、“carb”、“caro”和“碳”。請注意,在此問題中,空字串不被視為字首,但每個非空字串都被視為其本身的字首。在日常語言中,我們傾向於用字首來縮略單詞。例如,“碳水化合物”通常被縮寫為“carb”。在這個問題中,給定一組單詞,您將為每個單詞找到唯一標識它所代表的單詞的最短字首。
在下面的樣本輸入中,“碳水化合物”可以縮寫為“碳水化合物”,但不能縮寫為“碳水化合物”(或任何較短的碳水化合物),因為列表中還有其他以“碳水化合物”開頭的詞。
精確匹配將覆蓋字首匹配。例如,字首“car”與給定的單詞“car”完全匹配。因此,人們毫不含糊地理解,“CAR”是“CAR”的縮寫,而不是“CAR”或列表中以“CAR”開頭的任何其他詞的縮寫。輸入
輸入至少包含兩行,但不超過1000行。每一行包含一個單詞,由1到20個小寫字母組成。
輸出量
輸出包含與輸入相同的行數。輸出的每一行包含輸入的對應行中的單詞,後面是一個空格,最短的字首唯一地(沒有歧義)標識這個單詞。
樣本輸入
carbohydrate
cart
carburetor
caramel
caribou
carbonic
cartilage
carbon
carriage
carton
car
carbonate樣本輸出
carbohydrate carboh
cart cart
carburetor carbu
caramel cara
caribou cari
carbonic carboni
cartilage carti
carbon carbon
carriage carr
carton carto
car car
carbonate carbona
題目連結: http://poj.org/problem?id=2001
題解:
這是trie(字典)樹模板題,字典樹+字首的東西,給節點打個標記就行 與計數一樣 某個單詞的字元走到只標記過一次的節點(證明字元節點只有該單詞走過 可以代表該單詞)就行了。想了解 字典樹(點選即可)
AC 程式碼:
#include<stdio.h>
#include<string.h>
#define N 2501
int trie[N][27];
int trie_flag[N];
int tot=0;
void insert(char *s){//插入單詞
int i,id,len,root=0; len=strlen(s);
for(i=0;i<len;i++)
{ id=s[i]-'a';
if(!trie[root][id])trie[root][id]=++tot;
trie_flag[trie[root][id]]++; //給該字元節點打一個標記(計數)
root=trie[root][id];
}
}
void search(char *s){
printf("%s ",s);
int i,len,id,root=0;len=strlen(s);
for(i=0;i<len;i++)
{
printf("%c",s[i]);
id=s[i]-'a';
if(trie_flag[trie[root][id]]==1)break;//找到節點為 只標記過1次的
root=trie[root][id];
}
printf("\n");
}
int main()
{ char s[1005][25];int i=0,n=0;
memset(trie,0,sizeof(trie));
memset(trie_flag,0,sizeof(trie_flag));
while(scanf("%s",&s[n])!=EOF)insert(s[n++]);//輸入單詞表
while(n--)search(s[i++]);//輸出結果
return 0;
}