题目链接:http://poj.org/problem?id=2001
题目翻译:
POJ 2001:最短前缀
前缀是一个字符串是一个给定字符从第一字符开始的字串。例如:carbon的前缀有,c,ca,car,carb,carbo,carbon等。
PS:在这个问题中空字符串不看作前缀。但是每一个非空的字符串它自身可以看作自身的一个前缀。在每种语言中,我们倾向于用前缀来代表这个单词的缩写,例如"carhohydrate"常常缩写成carb.在这个题目中,我们给出一系列单词,你需要找到可以唯一代表每个单词的最短前缀.
我的第一道字典树题目:
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
using namespace std;
char ans[100];
char str[1005][25];
const int maxn = 26;
typedef struct TrieNode ///字典树节点声明
{
int ccount; ///该节点代表的单词是多少个单词的前缀
struct TrieNode *son[maxn]; ///26个儿子。
}Trie;
void insertWord(Trie *root,char word[]) ///将单词word插入到字典树
{
Trie *p = root; ///辅助指针
int i = 0;
char ch = word[i];
while(ch != '\0')
{
if(p->son[ch-'a']==NULL) ///如果这个字符不存在,建立节点
{
Trie *node = (Trie*)malloc(sizeof(Trie));
for(int i = 0; i < maxn; i++) ///该节点的所有儿子置为空
{
node->son[i] = NULL;
}
node->ccount = 1; ///新建立的节点,以该节点所代表单词为前缀的单词当前只有一个
p->son[ch-'a'] = node;
p = p->son[ch-'a'];
}
else
{
p->son[ch-'a']->ccount++;
p = p->son[ch-'a'];
}
ch = word[++i];
}
///p->ccount = 1; 去掉这句话就AC了,Why,感觉完全没关系,原来写上这一句我WA了三次。
}
void findWord(Trie *root,char word[])
{
int i = 0;
char ch = word[i];
Trie *p = root; ///辅助指针p
while(p!=NULL && ch!='\0')
{
p = p->son[ch-'a'];
ans[i++] = ch;
if(p->ccount == 1)
break;
ch = word[i];
}
ans[i] = '\0';
}
///释放字典树
void freeTrie(Trie *root)
{
for(int i = 0; i < maxn; i++)
{
if(root->son[i]!=NULL)
freeTrie(root->son[i]);
}
free(root);
}
int main()
{
Trie *root=(Trie*)malloc(sizeof(Trie));
for(int i = 0; i < maxn; i++)
{
root->son[i] = NULL;
}
int i = 0;
while(scanf("%s",str[i])!=EOF)
{
insertWord(root,str[i]);
i++;
}
for(int j = 0; j < i; j++)
{
findWord(root,str[j]);
printf("%s %s\n",str[j],ans);
}
freeTrie(root);
return 0;
}