您的位置:首页 > 其它

hdu 1251 统计难题 字典树

2016-07-20 23:40 405 查看
传送门:hdu1251统计难题

中文题目不做过多的解释

解题思路

已经接近于字典树的模板题目,每次把字典中的单词加入到树里面。

先是要创建这棵树,

1. 线定义结构体,先看我们定义的结构体

typedef struct Trie{
int v;
Trie *next[26];
}Trie;


创建字典树函数,字典树的创建如下图:




这个图对应的过程就是,

首先是一个根节点,他是所有单词的根源root

每个节点都有一个公共前缀,越往后公共前缀包含的字母数越多,叶子节点就是单词本身

比如说第一个叶子节点和第二个叶子节点,他们有公共的前缀是in

因为每一层的字母是肯定不会出现重复的,所以查询的时候是按照一层进行查找的

创建一个字典树的过程大致如下:

void createTrie(char *str)
{
int len = strlen(str);
Trie *p = &root, *q;
for(int i=0; i<len; ++i)
{
int id = str[i]-'a';//把这个字符串变为0~25的数字
if(p->next[id] == NULL)//如果这个字母在某一层不存在,就要创建它
{
q = (Trie *)malloc(sizeof(root));
q->v = 1;//初始化前缀为1
for(int j=0; j<26; ++j)//置空它的所有子节点
q->next[j] = NULL;
p->next[id] = q;
p = p->next[id];//创建完毕,让父层节点指向这个新加入的
}
else
{
p->next[id]->v++;//如果存在的话,前缀+1
p = p->next[id];//继续向下走
}
}
}


在树种查找一个单词,就是按照输入字母的每一位进行再树中的每一层中进行查找,大致过程如下:

int findTrie(char *str)
{
int len = strlen(str);
Trie *p = &root;
for(int i=0; i<len; ++i)
{
int id = str[i]-'a';
p = p->next[id];//如果存在一直找到叶子节点
if(p == NULL)//不存在就返回
return 0;
}
return p->v;
}


AC代码

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
typedef struct Trie{ int v; Trie *next[26]; }Trie;

Trie root;

void createTrie(char *str)
{
int len = strlen(str);
Trie *p = &root, *q;
for(int i=0; i<len; ++i)
{
int id = str[i]-'a';
if(p->next[id] == NULL)
{
q = (Trie *)malloc(sizeof(root));
q->v = 1;
for(int j=0; j<26; ++j)
q->next[j] = NULL;
p->next[id] = q;
p = p->next[id];
}
else
{
p->next[id]->v++;
p = p->next[id];
}
}
}

int findTrie(char *str)
{
int len = strlen(str);
Trie *p = &root;
for(int i=0; i<len; ++i)
{
int id = str[i]-'a';
p = p->next[id];
if(p == NULL)
return 0;
}
return p->v;
}

int main()
{
char str[15];
int i;
for(i=0; i<26; ++i)
root.next[i] = NULL;
while(gets(str) && str[0]!='\0')
createTrie(str);
memset(str, 0, sizeof(str));
while(scanf("%s", str) != EOF)
{
int ans = findTrie(str);
printf("%d\n", ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: