原题链接: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++]);
}
}