水题不水之字典树(Tire tree)

        今天碰到了一个水题不水。题目链接如下:http://acm.nyist.net/JudgeOnline/problem.php?pid=163

        第一感觉就是用字符串存储,然后一个一个地比较,然后,结果你们懂的,显然是TLE(超时),直接给我一个TLE错误,我了个去,然后 没办法才用的字典树。

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

提交的最后AC代码如下所示:

#include <iostream>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <cstdio>
using namespace std;

struct TireTree{
	TireTree* child[10];
	int		 number;
};

void DestroyTireTree(TireTree* root){//destroy a tire tree
	if(!root)//root is null
		return;
	for(int i= 0; i< 10; ++i){//destroy child
		DestroyTireTree(root->child[i]);
	}
	delete root;//destroy root
}

TireTree* CreateNode(int inode){
	TireTree* node = new TireTree;
	node->number = inode;
	memset(node->child, 0, sizeof(TireTree*)*10);//child is null
	return node;
}

bool InsertToTireTree(TireTree* root, int iNode, int* bit, int ilen, int iStep){
	if(root->number){
		return false;
	}
	if(iStep == ilen-1){//the last bit
		if(root->child[bit[iStep]]){//has a prefix
			return false;
		}else{
			root->child[bit[iStep]] = CreateNode(iNode);
			return true;
		}
	}else{
		if(!root->child[bit[iStep]]){//child is null
			root->child[bit[iStep]] = CreateNode(0);
		}
		return InsertToTireTree(root->child[bit[iStep]], iNode, bit, ilen, iStep+1);
	}
}

void HandleEachCase();

int main(){
	int iCaseCount;
	cin>>iCaseCount;
	while(iCaseCount--){
		HandleEachCase();
	}
}

void HandleEachCase(){
	int n;
	int number[100000];
	scanf("%d", &n);
	for(int i= 0; i< n; ++i){
		scanf("%d", number+i);
	}
	int bit[10];
	int ilen;
	TireTree* root = CreateNode(0);
	int tmp;
	bool ok= true;
	for(int i= 0; i< n; ++i){
		tmp = number[i];
		ilen = 0;
		while(tmp){
			bit[ilen++]= tmp%10;
			tmp/= 10;
		}
		reverse(bit, bit+ ilen);
		if(!InsertToTireTree(root, number[i], bit, ilen, 0)){
			ok = false;
			break;
		}
	}
	if(ok){
		cout<<"YES\n"<<endl;
	}else{
		cout<<"NO\n";
	}
	DestroyTireTree(root);
}
	


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是C++的字典树(Trie)模板: ```cpp #include <bits/stdc++.h> using namespace std; const int N = 1e5 + 5, M = 26; int n, m; int son[N][M], idx; bool is_end[N]; char str[N]; void insert() { int p = 0; for (int i = 0; str[i]; i++) { int u = str[i] - 'a'; if (!son[p][u]) son[p][u] = ++idx; p = son[p][u]; } is_end[p] = true; } bool find() { int p = 0; for (int i = 0; str[i]; i++) { int u = str[i] - 'a'; if (!son[p][u]) return false; p = son[p][u]; } return is_end[p]; } int main() { cin >> n >> m; while (n--) { scanf("%s", str); insert(); } while (m--) { scanf("%s", str); if (find()) puts("Yes"); else puts("No"); } return 0; } ``` 在这个模板中,我们使用一个整数数组son来表示每个节点的子节点。我们还使用一个bool数组is_end来表示从根节点到当前节点的路径是否为一个单词。 在insert函数中,我们遍历输入的字符串,并检查该字符的子节点是否存在,如果不存在,我们就创建一个新的子节点。最后,我们将当前节点标记为一个单词的结尾。 在find函数中,我们遍历查询字符串,并检查是否存在该字符的子节点。如果当前字符的子节点不存在,则该字符串不在字典树中。最后,我们检查当前节点是否标记为一个单词的结尾。如果是,我们返回true,否则返回false。 这个模板的时间复杂度为O(nm),其中n是字典树中单词的数量,m是查询的数量。由于每个单词的长度为O(k),因此总运行时间为O(k(n+m)),其中k是单词的平均长度。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值