今天找了一道关于Tire的问题,题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1251
处理关于前缀出现次数的问题,定义结点存放分支的个数,依次往下循找,如果合理,则返回分支个数否则返回零。
/****************************华丽的分割线~~**********************************/
字典树又称单词查找树,是一种树形结构,哈希树的变种,典型应用是用于统计,排序和保存大量的字符串,类似于字典的结构,它的优点是利用字符串的公共前缀来节约存储空间,最大限度的减少无谓的字符串比较,查询效率比哈希表高.
基本性质:
根结点不包括任何字符,除此之外,每个节点对应一个字符,从根结点出发,路径上经过的字符连接起来,为该节点对应的字符串,每个节点有多个子节点.
基本操作:
常见的有插入,查找,修改.
实现过程:
我们可以根据查字典的方法来进行查找和修改操作.
第一步:对根节点的子节点与需要查询的字符串首字母(即首关键码)进行匹配,正如我们要查询love这个单词,首先限定的范围即是由'l'开头的.
第二步:在相应的子树上,取的第二个关键码,如果为love,这里即为'o'.
第三步:重复第二步的递归.
第四步:若所以关键码被查询完,则可以读取相应的信息,本题信息为出现的次数.
Ac code:
#include<iostream>
#include<stdio.h>
#include<cstdio>
using namespace std;
struct node
{
int branchs; //info 出现的次数
node *next[26]; //字符种类n,即子节点的个数
};
void insert(char s[],node *T) //插入操作
{
int i=0,k,j;
node *p,*q;
p=T;
while(s[i])
{
k=s[i]-'a'; //求出关键码的位置
if(p->next[k]==NULL) //如果此位置原先为空,则加入该字符,并出现次数加1
{
q=new node;
q->branchs=1; //置为1
for(j=0;j<26;++j) //结点的初始化
q->next[j]=NULL;
p->next[k]=q; 插入该节点
}
else
p->next[k]->branchs++; //出现过,则次数加1
p=p->next[k]; //往下级检索
++i;
}
}
int search(char s[],node *T)
{
int i=0,ans,k;
node *p=T;
if(p==NULL) return 0;
while(s[i])
{
k=s[i]-'a';
if(p->next[k]==NULL) return 0; //往下循找为空,则不符合,直接返回零
ans=p->next[k]->branchs;
p=p->next[k];
++i;
}
return ans;
}
int main()
{
node *T=new node;
T->branchs=0; //初始,根节点不包括任何字符
int j;
char s[11];
for(j=0;j<26;++j) T->next[j]=NULL;
while(gets(s)) //gets为c语言函数
{
if(s[0]=='\0') break;
insert(s,T);
}
while(gets(s)!=NULL)
printf("%d\n",search(s,T));
// system("pause");
return 0;
}