字典树--字符串快速检索法

字典树

又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:利用字符串的公共前缀来节约存储空间,最大限度地减少无谓的字符串比较,查询效率比哈希表高。

它有3个基本性质:根节点不包含字符,除根节点外每一个节点都只包含一个字符。 从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串。 每个节点的所有子节点包含的字符都不相同。

  其基本操作有:查找 插入和删除,当然删除操作比较少见.我在这里只是实现了对整个树的删除操作,至于单个word的删除操作也很简单.

典型应用:

  1:串的快速检索:给出N个单词组成的熟词表,以及一篇全用小写英文书写的文章,请你按最早出现的顺序写出所有不在熟词表中的生词。

  在这道题中,我们可以用 数组枚举,用哈希,用字典树,先把熟词建一棵树,然后读入文章进行比较,这种方法效率是比较高的。

2:串排序
  给定N个互不相同的仅由一个单词构成的英文名,让你将他们按字典序从小到大输出

  用字典树进行排序,采用 数组 的方式创建字典树,这棵树的每个结点的所有儿子很显然地按照其字母大小排序。对这棵树进行先序遍历即可。

3:最长公共前缀问题:
  对所有串建立字典树,对于两个串的最长公共前缀的长度即他们所在的结点的公共祖先个数,于是,问题就转化为最近公共祖先问题(以后补上)。


ACM用模板:

#include <iostream>
using namespace std;
#define MAX 26 //字符集大小

typedef struct TrieNode {
	int nCount;
	struct TrieNode *next[MAX];
}TrieNode;

TrieNode Memory[1000000];
int allocp =0;

TrieNode *CreateTrieNode() {
	int i;
	TrieNode *p;
	p = &Memory[allocp++];
	p->nCount = 1;
	for(i =0 ; i < MAX ; i++) {
		p->next[i] = NULL;
	}
	return p;
}

void InsertTrie(TrieNode * &pRoot , char*s) {
	int i, k;
	TrieNode *p;
	if(!(p = pRoot)) {
		p = pRoot = CreateTrieNode();
	}
	i = 0;
	while(s[i]) {
		k = s[i++] - 'a';
		if(p->next[k])
			p->next[k]->nCount++;
		else
			p->next[k] = CreateTrieNode();
		p = p->next[k];
	}
}
/*查询该前缀出现次数*/
/*若查询该词出现次数
  则所有的count初始化为0
  并去除所有对count的操作
  只在每次InsertTrie末尾加 p->nCount++; 
*/ 
int SearchTrie(TrieNode * &pRoot , char*s) {
	TrieNode *p;
	int i , k;
	if(!(p = pRoot)) {
		return 0;
	}
	i = 0;
	while(s[i]) {
		k = s[i++] -'a';
		if(p->next[k] == NULL) return 0;
		p = p->next[k];
	}
	return p->nCount;
}

int main()
{
	TrieNode *ROOT = NULL;
	InsertTrie(ROOT,"see");
	InsertTrie(ROOT,"seeda");
	InsertTrie(ROOT,"seedb");
	InsertTrie(ROOT,"seeda");
	cout<<SearchTrie(ROOT,"seeda")<<endl;
	cout<<SearchTrie(ROOT,"seedb")<<endl;
	cout<<SearchTrie(ROOT,"see")<<endl;
	return 0;
} 

其他大型应用典型模板:

#include <iostream>
using namespace std;
#define MAX 26 //字符集大小
typedef struct TrieNode {
	int nCount; //记录该字符出现次数
	struct TrieNode *next[MAX];
}TrieNode;
TrieNode Memory[1000000];
int allocp =0;
/*初始化*/
void InitTrieRoot(TrieNode **pRoot) {
	*pRoot = NULL;
}
/*创建新结点*/
TrieNode *CreateTrieNode() {
	int i;
	TrieNode *p;
	p =&Memory[allocp++];
	p->nCount =1;
	for(i =0 ; i < MAX ; i++) {
		p->next[i] = NULL;
	}
	return p;
}
//插入	  
void InsertTrie(TrieNode **pRoot , char*s) {
	int i , k;
	TrieNode *p;
	if(!(p =*pRoot)) {
		p =*pRoot = CreateTrieNode();
	}
	i =0;
	while(s[i]) {
		k = s[i++] -'a'; //确定branch
		if(p->next[k])
			p->next[k]->nCount++;
		else
			p->next[k] = CreateTrieNode();
		p = p->next[k];
	}
}
//查找			  
int SearchTrie(TrieNode **pRoot , char*s) {
	TrieNode *p;
	int i , k;
	if(!(p =*pRoot)) {
		return 0;
	}
	i =0;
	while(s[i]) {
		k = s[i++] -'a';
		if(p->next[k] == NULL) return 0;
		p = p->next[k];
	}
	return p->nCount;
}



  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
### 回答1: 统计不同字符个数可以通过使用字典来实现。具体步骤如下: 1. 定义一个空字典,用于存储每个字符出现的次数。 2. 遍历字符串中的每个字符,如果该字符已经在字典中出现过,则将该字符对应的值加1;否则,在字典中添加该字符,并将其对应的值初始化为1。 3. 最后,遍历字典,统计不同字符的个数。 示例代码如下: ```python s = "hello, world!" d = {} for c in s: if c in d: d[c] += 1 else: d[c] = 1 count = len(d) print("不同字符个数为:", count) ``` 输出结果为: ``` 不同字符个数为: 10 ``` 其中,字典d的内容为: ``` {'h': 1, 'e': 1, 'l': 3, 'o': 2, ',': 1, ' ': 1, 'w': 1, 'r': 1, 'd': 1, '!': 1} ``` ### 回答2: 在程序设计中,有时需要统计一个字符串中不同字符的个数。Python中的字符串是不可改变的序列,可以通过遍历字符串的每个字符,利用集合的特性来统计不同字符个数。以下是一个简单的例子: ```python s = 'abcaabc' count = len(set(s)) print(count) ``` 解释:首先定义一个字符串`'abcaabc'`,然后通过`set`函数将字符串中的字符去重,得到一个只包含不同字符的集合,最后利用`len`函数统计集合中元素的个数,即不同字符的个数。运行结果为`3`,即字符串`'abcaabc'`中不同字符的个数。 另外,如果想要统计字符串中每个字符出现的次数,可以使用Python内置的`collections`模块中的`Counter`函数,代码如下: ```python from collections import Counter s = 'abcaabc' count = Counter(s) print(count) ``` 解释:首先导入`collections`模块中的`Counter`函数,然后定义字符串`'abcaabc'`,接着调用`Counter`函数统计字符串中每个字符出现的次数,最后将结果打印出来。运行结果为`Counter({'a': 3, 'b': 2, 'c': 2})`,即字符串`'abcaabc'`中每个字符出现的次数分别为`a:3`、`b:2`、`c:2`。 总之,Python中统计字符串中不同字符的个数可以使用`set`函数,统计每个字符出现次数可以使用`collections`模块中的`Counter`函数,这些函数都可以帮助我们更方便地对字符串进行处理和分析。 ### 回答3: 在计算机编程或数据处理中,经常需要统计字符串中不同字符的个数。Python中有多种方可以实现这个目标,下面将对其中几种方进行介绍。 方一:利用集合(set)的特性 集合是Python中的一种数据类型,它的特点是不允许有重复元素,所以我们可以将字符串中的字符逐一添加到集合中,并统计集合的长度即可。具体代码如下: ``` string = "hello world" char_set = set(string) count = len(char_set) print(count) ``` 输出结果为9,说明"hello world"中共有9种不同的字符。 方二:利用字典(dictionary)的特性 字典是Python中的另一种数据类型,它类似于一个关联数组,可以存储一对“键-值”映射关系。我们可以将字符串中的字符作为“键”,将出现的次数作为“值”,逐一添加到字典中,最后输出字典中“键”的数量即可。具体代码如下: ``` string = "hello world" char_dict = {} for char in string: if char in char_dict: char_dict[char] += 1 else: char_dict[char] = 1 count = len(char_dict) print(count) ``` 输出结果同样为9。 方三:利用collections模块中的Counter类 Python的collections模块中有一个Counter类,可以用来统计字符串中每个字符出现的次数。具体做是先将字符串转换成列表,然后将列表传入Counter类的构造函数中即可,最后输出Counter类中元素的数量即可。具体代码如下: ``` from collections import Counter string = "hello world" char_list = list(string) char_counter = Counter(char_list) count = len(char_counter) print(count) ``` 输出结果同样为9。 总之,以上这几种方都可以用来统计字符串中不同字符的个数,具体的选择取决于具体的需求和使用场景。其中,方一使用起来比较简单,但可能会占用较多的内存;方二使用起来稍微麻烦一些,但可以方便地统计每个字符出现的次数;方三则可以很方便地使用collections模块中的其它功能,如most_common()方来查找出现次数最多的字符等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值