POJ 2001:Shortest Prefixes(字典树入门)

题目链接: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;
}



  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值