杭电1075——What Are You Talking About(字典树应用)

博客介绍了杭电1075问题的解决方案,通过使用字典树(Trie)来高效地处理英文到火星文的映射。文章解释了字典树的数据结构及其在字符串查询中的优势,如减少比较次数和提高查询效率。内容包括字典树的构建、查找算法以及最终的AC代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1075

主要算法:
一开始使用数组存储英文和对应的火星文,排序,再折半查找,结果超时。后来,百度了下,改成用字典树存储。其典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希树高。

字典树的数据结构

# define MAX 26
typedef struct Trie{
    struct Trie *next[MAX];
    char *eng;//此处可以根据需要修改
}Trie;

由于题中限定只有小写字母,所以MAX为26。如果是大小写字母,则MAX为52。如果是大小写字母和数字,则MAX为62。next是指向下一层的指针数组,设一节点为p。若p->next[k]==NULL,则该节点下一层没有’a’+k的节点,如果p->next[k]!=NULL,则说明该节点下一层有’a’+k的节点。该结构中的char *eng,可以根据题意修改。此题需要记录火星文对应的英文,所以,设置一个eng。当在一个火星文单词的末端节点的eng中存储了其对应的英文,其余情况下,eng为NULL。

这里写图片描述

字典树的查找:
(1) 每次从根结点开始一次搜索;
(2) 取得要查找关键词的第一个字母,并根据该字母选择对应的子树并转到该子树继续进行检索;  
(3) 在相应的子树上,取得要查找关键词的第二个字母,并进一步选择对应的子树进行检索。   
(4) 迭代过程……   
(5) 在某个结点处,关键词的所有字母已被取出,则读取附在该结点上的信息,即完成查找。

AC代码

# include<stdio.h>
# include<stdlib.h>
# include<string.h>
# define MAX 26
typedef struct Trie{
    struct Trie *next[MAX];
    char *eng;
}Trie;

Trie * root=NULL;

char word[30010];
void transOneLine();
void insertTrie(char str1[],char str2[]);
void translate();

int main()
{
    translate();
    return 0;
}

void translate()
{
    int i;
    root=(Trie *)malloc(sizeof(Trie));
    for(i=0;i<MAX;i++)
        root->next[i]=NULL;
    root->eng=NULL;
    //输入单词,建立字典树
    char str1[12],str2[12];
    while(1)
    {
        scanf("%s",str1);
        if(strcmp(str1,"START")==0)
            continue;
        else if(strcmp(str1,"END")==0)
            break;
        scanf("%s",str2);
        insertTrie(str1,str2);
    }
    getchar();//避免gets把换行读成一个空行
    //输入要翻译的文字
    while(1)
    {
        gets(word);
        if(strcmp(word,"START")==0)
            continue;
        else if(strcmp(word,"END")==0)
            break;
        transOneLine();
        printf("\n");
    }
}

void insertTrie(char str1[],char str2[])
{
    if(!root)
        return;
    Trie *p=root;
    int len=strlen(str2),i,j;
    for(i=0;i<len;i++)
    {
        int k=str2[i]-'a';
        if(p->next[k]==NULL)
        {
            p->next[k]=(Trie *)malloc(sizeof(Trie));
            p->eng=NULL;
            p=p->next[k];
            for(j=0;j<MAX;j++)
                p->next[j]=NULL;
        }
        else
            p=p->next[k];
    }
    p->eng=(char *)malloc(sizeof(char)*12);
    strcpy(p->eng,str1);
}


void transOneLine()
{
    int j;
    char temp[12];
        for(j=0;word[j]!='\0';)
        {
            int k=0;
            while(word[j]>='a'&&word[j]<='z')
            {
                temp[k++]=word[j++];
            }
            temp[k]='\0';
            if(k>0)
            {
                Trie * p=root;
                int t;
                for(t=0;t<k;t++)
                {
                    int id=temp[t]-'a';
                    if(p->next[id]==NULL)
                        break;
                    p=p->next[id];
                }
                if(t==k&&p->eng)
                    printf("%s",p->eng);
                else
                    printf("%s",temp);
            }
            while((word[j]<'a'||word[j]>'z')&&word[j]!='\0')
                printf("%c",word[j++]);
    }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值