【hiho一下】第二周 Trie树

题目1 : Trie树

题目原文:http://hihocoder.com/contest/hiho2/problem/1

【题目解读】

提示说明使用Trie树(即,字母树,前缀树)已经很清楚了,难度就在实现。鄙人不才,树结构和指针学的跟翔没有两样。。。求助大神和查阅资料之后,憋了几天才写出来。

【hiho提示】

【提示一】【提示二】是介绍使用Trie树。每次拿到前缀之后,在树上找到对应的结点,然后统计这个节点以及其子树里有多少个标记成单词的节点。

【提示三】提出,【二】中“统计”单词数量的方法:在最开始置所有L[T]=0,然后每次添加一个新的单词的时候,都将它经过的所有结点的L[T]全部+1,这样构建完这棵Trie树的时候,我也就能够同时统计到所有L[T]了。即在创建时遍历

【编写细节】

编写树一般有两种思路:

(1)父节点表示法,每个节点只记录自己的父节点。

(2)孩子链表表示法,每个节点记录自己的所有孩子节点,并且将其串入一个链表。为节省存储空间我选用后者。

之后,创建Trie树的方式有:

(1)每个节点有最大分支数个指针,指针指向另一个新节点。另外每个节点保存一个token值。我选用这种。

(2)Trie本质是一个DFS树,其实常用数据结构是转移矩阵,但是太费空间,所以用指针。

(3)看到一种二叉树表示的数据结构:每个节点的左子树是儿子节点链表,指向大儿子;右子树是兄弟节点链表,指向与父节点同级的下一个兄弟父节点不与大儿子之外的儿子连接,通过大儿子连接

以上是树的整体结构,接下来是一些编写的细节问题:

(1)C++ struct 与 C 中的 struct 不同,struct name{}; 后 name 可以直接作为类型名使用,并且可以写构造函数、析构函数;

(2)结构体如果有对于自身的引用,只能引用指针不能引用实例;例如以下是错误的

struct A
{
    A test;
};

但是这样就是正确的

struct A
{
    A* test;
};

(3)
全局变量的初始值一定为0 / NULL,局部变量的初始值则不一定;

(4)指针定义时并不分配内存,C/C++ 分配内存使用 malloc 或 new,两者具体差别见:http://blog.163.com/yangjun1988422@126/blog/static/4741291720084305615602/

使用 malloc 格式:type* p = (type*)malloc(sizeof(type))

这次我反正是体会到了他俩的一个区别:malloc 根本不调用构造函数、析构函数啊尼玛!

所以,也有人理解:new = malloc + 构造函数;delete = free + 析构函数

【AC代码】

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

const int branch = 26;

struct tnode
{
	int n;
	tnode* child[branch];

	//tnode():n(0)				// malloc不能调用构造函数 
	//{
	//	for(int k=0; k<26; k++)
	//		child[k] = NULL;
	//}		
};

long	n, m;
char	str[35];
char	base = 'a';
int		len;

tnode* create()
{
	tnode* tnew = (tnode*)malloc(sizeof(tnode));
	tnew->n = 0;
	for(int k=0; k<branch; k++)
		tnew->child[k] = NULL;
	return tnew;
}

int main()
{
	scanf("%ld", &n);
	tnode* root = create();
	root->n = -1;				// flag -1: root
	tnode* tmp = NULL;
	
	while(n--)
	{
		scanf("%s", str);
		len = strlen(str);
		tmp = root;
		for(int i=0; i<len; i++)
		{
			if(tmp->child[str[i]-base] == NULL)
			{
				tmp->child[str[i] - base] = create();
			}
			tmp->child[str[i]-base]->n++;
			tmp = tmp->child[str[i] - base];
		}
	}

	scanf("%ld", &m);
	while(m--)
	{
		scanf("%s", str);
		tmp = root;
		len = strlen(str);
		for(int j=0; j<len; j++)
		{
			tmp = tmp->child[str[j] - base];
			// if the predixs never appear
			if(tmp == NULL)
				break;
		}
		if(tmp == NULL)
			printf("0\n");
		else	
			printf("%d\n", tmp->n);
	}

	return 0;
}

    原文作者:Trie树
    原文地址: https://blog.csdn.net/ironyoung/article/details/37818639
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞