字典树的理解(数组实现)

  • Post author:
  • Post category:其他

正规的字典树的数据结构,使用指针指向下一层子树。但是有写空间要求较高的题目使用指针的方法有可能会MLE。所以使用数组来实现字典树的数据结构是一种更好更紧凑的方法,这种方法更为保险
以hdu 1251为例

题目大意

很多单词只由小写字母组成,不会有重复的单词出现,统计出以某一个字符串为前缀的单词数量。

前半部分读入:

dcba
debf

对于这一部分的读入我们要做到的是建树和统计

int trie[1000010][26];
int num[1000010]={0};
int pos=0;
void Insert(char str[]){
	int p=0;
	for(int i = 0;str[i];i++){
		int n=str[i]-'a';
		if(trie[p][n]==0)
			trie[p][n]=++pos;//独立编号
		p=trie[p][n];
		num[p]++;//统计
	}
}

第一个字符串建树后:

层数/26个字母 0 1 2 3 4 5
0 1
1 2
2 3
3 4
4
5
6

二维数组中每个元素的值,都表示下一跳要去哪一层

第二个字符串建树后:

层数/26个字母 0 1 2 3 4 5
0 1
1 2 5
2 3
3 4
4
5 6
6 7

从第一层跳到第二层中发现第二层中有两个元素值。说明他们有共同的前缀
后一个字符串的下一跳就到第五层了

我们对于没有相同前缀的独立子串,都给它的每一个字符一个单独的编号,方便查找以某一个字符串为前缀的单词数量

另设一个num[ ]数组来存放以当前子串为前缀的单词数量
以本题为例:
num[1]=>以”d”为前缀的单词数量
num[6]=>以”bea”为前缀的单词数量
num[4]=>以”dcba”为前缀的单词数量

第二部分读入:
dcb
当建树和统计都完成后,剩下的就是一个查询的过程了,find( )函数的功能就是查找给出的字符串的每个前缀字串的单词数量

int Find(char str[]){
	int p=0;
	for(int i=0;str[i];i++){
		int n=str[i]-'a';
		if(trie[p][n]==0)
			return 0;
		p=trie[p][n];
	}
	return num[p];
}

以本题为例
Find()函数中的循环
先找了以d为前缀的单词个数=>num[1]
再找以dc为前缀的单词个数=>num[2]
再找以dcb为前缀的单词个数=>num[3]

但凡有等于0的情况,说明没有以当前字符串为前缀的单词,直接退出


版权声明:本文为qq_40409416原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。