您的位置:首页 > 其它

练习:Trie树(公共前缀)

2016-01-27 14:52 134 查看
Trie树,又称字典树,单词查找树或者前缀树,是一种用于快速检索的多叉树结构。

它的精髓在于利用字符串的公共前缀来节约存储空间。从根节点到某一个节点,路径上经过的字符连接起来,为该节点对应的字符串。(举例如下图)



Trie树的应用很多,主要是以下几个方面:

(1)正如“前缀树”的定义一样,Trie树可以方便地检索字符串,查找字符串的公共前缀等。更为重要的是,建立Trie树的过程,其实也是查询的过程。

(2)排序。只要先序遍历整棵树,输出相应的字符串便是按字典序排序的结果。

(3)其他数据结构和算法的基础:如AC自动机、后缀树等。

下面通过hihoCoder上的一个例子,编程练习。

给定一个含有n(n≤100000)个单词的字典,每个单词由不超过10个的小写英文字母组成(可能存在相同的单词,此时应将其视作不同的单词)。

接下来有m(m≤100000)次询问,每次询问要求回答字典中以给定字符串为前缀的单词的个数

【样例输入】

5

babaab

babbbaaaa

abba

aaaaabaa

babaababb

5

babb

baabaaa

bab

bb

bbabbaab

【样例输出】

1

0

3

0

0

【我的程序】

这是Trie树的经典练习,在程序中,我采用孩子兄弟表示法来储存这棵Trie树。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct triNode //孩子兄弟表示法
{
char c;
long int num;
struct triNode* fChild;
struct triNode* rCousin;
}* triTree;

triTree newTree(char c) //新建一棵子树
{
triTree p=(triTree) malloc(sizeof(struct triNode));
p->c=c;
p->num=1;
p->fChild=NULL;
p->rCousin=NULL;
return p;
}

void dictionary(triTree t) //建立字典树
{
long int n,i;
char s[11];
scanf("%ld",&n);

for (i=0;i<n;i++)
{
scanf("%s",s);
long int len=strlen(s),j,k;
triTree x=t,y;

for (j=0;j<len;j++)
{
y=x->fChild;
if (y==NULL) //当前结点没有子树,则将剩余字符串全部插入
{
for (k=j;k<len;k++)
{
x->fChild=newTree(s[k]);
x=x->fChild;
}
break;
}

int flag=0;
while (y!=NULL)
{
if (y->c==s[j]) {flag=1;break;}
x=y;
y=y->rCousin;
}

if (flag==0) //未找到当前字符,则增加一棵子树作为右兄弟
{
x->rCousin=newTree(s[j]);
x=x->rCousin;
for (k=j+1;k<len;k++)
{
x->fChild=newTree(s[k]);
x=x->fChild;
}
break;
}
else //找到当前字符,将经过当前结点的字符串个数加1
{
x=y;
x->num++;
}
}
}
}

void response(triTree t) //查询过程和建树过程同理,且更简单
{
long int m,i;
scanf("%ld",&m);

for (i=0;i<m;i++)
{
char s[30];
scanf("%s",s);
long int len=strlen(s),j;
triTree y=t;

for (j=0;j<len;j++)
{
y=y->fChild;
if (y==NULL) {printf("0\n");break;}

while (y!=NULL)
{
if (y->c==s[j]) break;
y=y->rCousin;
}
if (y==NULL) {printf("0\n");break;}
}

if (j==len) printf("%ld\n",y->num);
}
}

int main()
{
triTree t=newTree('0');
dictionary(t);
response(t);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: