`
kmplayer
  • 浏览: 498562 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Tire树

阅读更多
Tire树:
先简单解释一下Trie。“Trie”这个单词来自于"retrieve",可见它的用途主要是字符串查询。Trie不发tree的音,而发try的音。

应用
题目大意:
统计子串出现的次数,规定子串的长度不超过8.
http://acm.scs.bupt.cn/onlinejudge/showproblem.php?problem_id=1302

trie算法的思路大概如下:
对输入的长串S 想将所有长度位1-8的子串存入trie树,并在子串末节点上记录下字串出现的次数,然后针对每个输入的查询串s 只要在这颗树上查找 一遍就能找到得到该子串出现的次数。

仍段代码先:
#include <iostream>

using namespace std ;

class trie
{
private :
		int count[26] ;
		trie * child[26] ;
public :
		trie ()
		{
			int i ;
			for ( i = 0 ; i < 26 ; i++ )
			{
				count[i] = 0 ;
				child[i] = NULL ;
			}
		}
		~trie ()
		{
			int i ;
			for ( i = 0 ; i < 26 ; i++ )
			{
				delete child[i] ;
			}
		}
		void insert ( const char *key , const int & leng ) //生成了字典树,这次操作统计的次数全部以*key开头
		{
			if ( leng == 0 )
				return ;
			int index = *key - 'a' ;
			if ( child[index] == NULL ) child[index] = new trie ;
			count[index]++ ;
			child[index] -> insert ( key + 1 , leng - 1 ) ;
		}
		int quary ( const char *key ) //返回子串出现的次数
		{
			if ( * ( key + 1 ) == '\0'  ) //最后一个字符
				return count[*key - 'a'] ;
			if ( child[*key - 'a'] == NULL ) //只有遇到不存在的部分子串,必定返回0.
				return 0 ;
			return child[*key - 'a'] ->quary ( key + 1 ) ; //递归寻找下一个字符
		}
} ;
char s[32768 + 10] ;
int main ()
{
	int stringLength  , quaryNumber , left , right , substringLength , test = 1 ;;
	while ( scanf ( "%s" , s ) != EOF )
	{
		trie stringTrie ;
		substringLength = 8  ;
		stringLength = strlen ( s ) ;
		for ( left = 0  ; left + substringLength <= stringLength ; left++  )
			stringTrie.insert ( s + left , substringLength ) ; //生成了字典树
		for ( substringLength = 7 ; left < stringLength ; left ++ , substringLength-- )
			stringTrie.insert ( s + left , substringLength ) ; //添加最后7个开头子串的统计数
		scanf ( "%d" ,  &quaryNumber ) ;
		printf ( "Case %d:\n" , test++ ) ;
		while ( quaryNumber -- )
		{
			scanf ( "%s" , s ) ;
			printf ( "%d\n" , stringTrie.quary ( s ) ) ;
		}
	}
	return 0 ;
}



这个题目也可以用hash做.
基本思路:
这里采用的最简单的26进制的函数对子串进行hash,由于26^8 会超出int的范围所以在计算hash值时需要64位的整数。在算出每个子串的 hash值后就将相应的slot标记好,并记录下这个slot被标记过几次,然后对各查询子串也用相同的hash函数来处理,然后查询子串所在的slot 的计数器就行了。
#include<iostream>

using namespace std ;

typedef long long __int64 ;
char s[1<<16] ;
const int HASH_SIZE = 1<<18 ;
__int64 mark[HASH_SIZE] ;
int counter[HASH_SIZE] ;

int getHashVal ( __int64  tmp )
{
	return tmp&(HASH_SIZE-1) ;
}
void insert ( __int64 tmp )
{

	int val = getHashVal ( tmp ) ;
	int index = val ;

    //index代表下标和tmp的值不是对应的,因此每次都需要需要tmp对应的index.
	while ( mark[index] != -1 && mark[index] != tmp )
	{
		index++ ;
		if ( index == HASH_SIZE ) index = 0 ;
	}
	counter[index]++ ;
	mark[index] = tmp ;
}
int query ( __int64 tmp )
{
	int val = getHashVal ( tmp ) ;
	int index = val ;

	while ( mark[index] != -1 && mark[index] != tmp )
	{
		index++ ;
		if ( index == HASH_SIZE ) index = 0 ;
	}
	return counter[index] ;
}

int main()
{

	__int64 tmp ;
	int t ,  Q ;
	for ( t = 1 ; scanf ( "%s" , s ) != EOF ; ++t )
	{
		memset ( mark , -1 , sizeof ( mark ) ) ;
		memset ( counter , 0 , sizeof ( counter ) ) ;
		printf ( "Case %d:\n" , t ) ;
		for ( int i = 0 ; s[i] != '\0' ; ++i ) //s[i] != '\0',因此所有的子串都可以遍历到.
		{
			tmp = 0 ;
			for ( int k = 0 ; k < 8 && s[i + k] != '\0'; ++k ) //转化为27进制的一个数
			{
				tmp = tmp * 27 + s[i + k] - 'a' + 1 ;
				insert ( tmp ) ;
			}
		}
		scanf ( "%d" , &Q ) ;
		while ( Q-- )
		{
			scanf ( "%s" , s ) ;
			tmp = 0 ;
			for ( int i = 0 ; s[i] != '\0' ; ++i )
			{
				tmp = tmp * 27 + s[i] - 'a' + 1 ;
			}
			printf ( "%d\n" , query ( tmp  ) ) ;
		}
	}
	return 0;
}
分享到:
评论

相关推荐

    关于tire树

    关于tire树一些简单的使用和应用

    什么是Tire树1

    (2) 树有s个外部结点 (3) 树的高度等于X中最长串的长度 (4) 树中的结点数为O(n) (1) 在root结点中查找第('b'-'a'=1)号孩子指针,

    CQ V2.0分词bates(基于双数组tire树)

    NULL 博文链接:https://ansjsun.iteye.com/blog/441658

    tire树分析

    NULL 博文链接:https://tanghongjun1985.iteye.com/blog/548759

    trie_suffix.rar_suffix tire_suffix tr_tire_串匹配_后缀树

    后缀tire树(tire图),用于多字符串匹配。

    TIRE 字典树 论文

    Tire 字典树 方面的论文

    数据结构与算法面试题整理

    数据结构指的是“一组数据的存储...数据结构:数组、链表、栈、队列、散列表、二叉树、堆、跳表、图、Tire树 算法: 递归、排序、二分查找、搜索、哈希算法、贪心算法、分治算法、回溯算法、动态规划、字符串匹配算法。

    多叉树做的实现字典功能

    利用Tire树实现一个音域单词辅助记忆系统,完成相应的建表和查表程序。 程序主要实现对单词的插入、删除和查找。其中查找部分又分精确查找和模糊查找。 利用文件对单词进行保存和读取操作以增强程序的可用行性。

    DoubleArrayTrie:双端trie树的python实现

    DoubleArrayTrie 双端trie树的python实现 ...其与双数组Tire可以说在功能上互补; 在存储值很多且多有冲突、字符编码范围较大的情况下,双数组Trie树很可能在序列化到硬盘以及加载到内存的占用空间都远大于字典Trie树

    一个小型的全文检索引擎的DEMO

    里面基本包含了全文检索引擎的所有技术,包括词典分词,索引,检索等,其中词典分词采用的是基于双数组tire树的最大匹配法,索引部分参考了lucene的部分实现,检索部分应用了布尔检索和向量模型的排名算法,基本可以...

    CSC148 A2 Students.7z

    包括 插入 删除 是否包含 自动补全 两棵tire树的合并 自动纠错

    经典AC自动机.cpp

    ac自动机,就是在tire树的基础上,增加一个fail指针,如果当前点匹配失败,则将指针转移到fail指针指向的地方,这样就不用回溯,而可以路匹配下去了

    java8集合源码分析-pangdan:面试相关技能

    红黑树、AVL树、Hash树、Tire树、B树、B+树。 图算法(比较少,也就两个最短路径算法理解吧) 计算机网络 OSI7层模型(TCP4层)等 数据库 数据库(最多的还是mysql,Nosql有redis) 索引(包括分类及优化方式,失效...

    JavaStudy:一角钱技术 All in One

    Tire树的基本实现和特性 并查集的基本实现和特性 剪枝的实现和特性 双向BFS的实现和特性 启发式搜索的实现和特性 AVL树和红黑树的实现和特性 位运算基础与实战要点 布隆过滤器的实现及应用 LRU Cache的实现及应用 ...

    基于双数组Trie_树中文分词研究

    对双数纽Trie 树(Double-Array Trie)分词算法进行了优化:在采用Trie 树构造 双数纽Trie 树的过程中,优先处理分支节点多的结点,以减少冲突;构造一个空状态序列; 将冲突的结点放入Hash表中,不需要重新分配...

    论文研究-嵌入式系统中基于trie树的拼音输入法的实现 .pdf

    嵌入式系统中基于trie树的拼音输入法的实现,李巧红,,介绍一种中文拼音输入法的实现方式,着重讨论了字库的设计及基于Trie树检索方法的实现。Trie树是基于关键码空间分解的树结构,其内�

    LeetCode:212 单词搜索Ⅱ

    这道题是DFS+前缀树,是一道标准的模板题 这里面的Tire类的定义写的方法与之前的 208 略有不同,但基本上一样。只是单独定义了一下TireNode节点类。 //定义节点,类/结构体 class TireNode { public: TireNode()...

    ACM国家集训队2006论文集

    ACM国家集训队2006论文集(动态树、动态规划、tire图、最短路算法、棋盘分割)

    数据结构_TIER_课程设计_代码实现

    《数据结构》)字典树课程设计《英语字典的维护与识别》的代码实现。。。。。

Global site tag (gtag.js) - Google Analytics