现在有一批中等数量级(十万级)的数据,格式如下:
ID NameInfo
0 北京市人民政府
1 国家安全局
2 上海市人民政府
3 八达岭长城
....... ................
现在要对此文件建立关键字索引。(例如:输入国家,可以快速的找到国家安全局。输入人民可以找到北京市人民政府
和 上海市人民政府);
要求建立的索引结构所占用的空间相对最少,但是关键字查找速度要很快。
现在考虑使用 Trie树,但是Trie树太浪费空间了。
不知大家有没有好的算法。尽情讨论!!!
|
没理解错的话,应该是类似SQL查询中like子句的功能吧。
1、搞个词典库,把每个关键字编号;
40万关键字+编号,按4个汉字组词算,需要(4*2 + 4) * 40W = 4.8M空间。
搜索方式可以使用简单的二分查找(此时可以省去编号占用的空间);但考虑这个库实际使用压力较大,采用hash较好。
记得哪里说过,hash数据量应该是存储区大小的7x%;以后再靠加大存储区去减少碰撞,效果已经不明显了。
采用悲观点的值,用8M空间吧。
如果内存紧张,可以不使用hash,改成按关键词排序后二分查找;这样查询效率稍微低一些,但可以节约4.8M空间(hash本身额外占用的3.2M,加上可以用关键词本身的数组下标当作编号而节约的每词4字节共1.6M的空间)。
2、把NameInfo切分,然后分析切分出的关键词在不在词典库里;在就把它记为关键字。
类似这样:
a、NameInfo 北京市人民政府
b、分词,分解为 北京 市 人民 政府 或 北京市 人民 政府
c、查词典,确认 北京 人民 政府 为关键字,且编号分别为123456 345667 456667
(根据你的举例,每条记录大概有3~4个关键字;以后都按4个关键字算;这些关键词仅用于建索引,不必实际存储)
3、另开一个指针数组,数组下标对应关键字编号(这需要40W × 4 = 1.6M字节),指针指向包含对应关键字的记录ID列表。
记录ID的列表可以采用动态分配或内存池。因为有10W记录,所以ID最少需要3字节;为以后扩充计,以下按四字节计算。
假设每条记录都有4个关键字,那么将需要4倍于记录数的节点空间(即需要4*4*10W=1.6M字节);如果用单链表实现,则还需要额外的4个字节保存next指针,即一共3.2M空间。
(用数组可以比链表减少一半空间消耗,但插入删除比较慢)。
现在,内存中大概是这样:
词典区(8M):
[关键字1 编号1][关键字2 编号2][关键字3 编号3]……
索引区(1.6M+3.2M=4.8M)
关键字编号=数组下标;
指针指向一个链表,链表保存对应的记录ID(或指向此记录的指针)
记录区(10W × 单条记录大小,假设你的系统还允许占用5M内存,则单条记录不能大于50字节;考虑一个ID要4字节,要求NameInfo不能大于23个汉字)
记录区可以是一个简单数组,此时ID可省略。
所有这些一共需要17.8M空间;若词典改成排序数组,则只需13M空间。
注意记录区ID字段按4字节计,但实际在记录区可以直接用数组下标代替ID,可节约10W×4=0.4M空间;此外,关键字编号只需3字节,前面全部是按4字节算的,也可以压缩一下。
总之,根据自己需要裁剪后,上面这个方案可以压缩到仅占用11M字节甚至更少。
以下按最优性能方案计算
插入效率:
需要若干次O(1)的hash查询(看分词算法的好坏了),以把分词结果对应到关键字编码上;然后建索引需要4次数组访问和4次链表插入操作(复杂度都是O(1))。
查询效率:
需要一次O(1)的hash查询,以把用户输入的关键词对应到编码上;然后拿这个编码当下标访问数组,取得查询结果链表;再根据链表记载把所有合适记录打印出来。
总的来说,插入、查询效率都是O(1);很容易扩充出删除操作(好像没这需求吧),且删除效率也是O(1)。
注意这个算法是个完全内存算法,它的响应速度是微秒甚至纳秒级;所以不必担心用二分法查找代替hash后会导致太大的性能损失。
如果将其改成完全磁盘算法(此时当然就不需要担心空间消耗了),即使考虑干扰因素,速度仍然可以保持在十几到几百毫秒的级别上。
——每秒显示25帧,人眼看起来就是连续动画,此时每帧就要滞留1000/25=40毫秒;200毫秒的延迟也不过是5个动画帧而已,一般用户感觉不到任何延迟。
当然,如果有外存的话,考虑40万关键字肯定不会用全、10W记录也不一定每一条都会访问到;那么最好的做法还是搞个cache,做成半内存算法:这样一方面不需要占用太多内存,同时还可以在大部分情况下保持微秒级响应速度。
(当然,如果用外存,还是直接用一些轻量级数据库更方便)
分享到:
相关推荐
关键字提取算法 在信息检索和自然语言处理领域,关键字提取算法是一个非常重要的技术。关键字提取算法的主要目的是从大量文档中自动地提取出能够代表文档主题和内容的关键词,以便于更好地理解和分析文档的内容。 ...
基于python 编写的 基于tfidf的关键字提取算法。
Java语言的DFA关键字过滤算法设计源码涵盖了一系列的文件和资源,主要用于实现高效的关键字过滤功能。在这一系列资源中,XML配置文件扮演了重要的角色,它们负责配置系统的运行参数和关键字库,使得系统能够根据不同...
下面将详细介绍关键字匹配的基本概念、常用算法以及其实现过程。 1. **基本概念** - **关键字**:在文本中具有特定意义的词汇或短语,通常是我们想要查找或关注的部分。 - **文本**:可以是单个文档、多个文档...
C语言实现的三段查找算法中,首先定义了必要的变量,如数组的起始和结束指针、段长以及目标关键字。初始时,整个数组范围被考虑在内,并被平均分成三段。在查找过程中,通过比较目标值与各段边界的值,不断调整查找...
排序和查找算法(如快速排序、二分查找)可能用于优化性能。 2. 文件读写:由于数据量可能较大,Java的IO流(如FileInputStream、BufferedReader)将用于读取和处理数据文件。 3. 多线程:为了提高处理效率,可能...
【标题】:“关键字查找工具” 在信息技术领域,关键字查找工具是一种高效、实用的软件应用,专为用户在大量文本数据中快速定位特定关键字而设计。它可以帮助用户在各种类型的文件中,例如文档、代码、邮件等,进行...
折半查找算法在顺序表中插入一个元素讲解 折半查找算法是一种常用的查找算法,它可以在已经排好序的顺序表中快速地找到某个元素。下面我们来详细讲解折半查找算法在顺序表中插入一个元素的过程。 折半查找算法的...
本文将详细探讨这些知识点,并结合“关键字过滤多模式匹配算法(支持中文)”这一主题,深入解析相关技术和应用。 首先,关键字过滤是一种技术,用于从大量文本数据中筛选出包含特定关键字或短语的信息。这种技术...
在此基础上,在强全序模块模式下提出了时态强简单候选关键字的概念,给出了明确的定义,并且给出了强全序候选关键字算法以及求取强简单候选关键字集算法;对算法的可终止性、正确性进行了证明,并对算法的复杂度进行...
总的来说,"一键搜索---根据关键字查找文本(快速搜索)"是Java编程中一个高效、灵活的文本搜索解决方案,其背后的技术涵盖了字符串处理、文件操作、算法运用等多个方面,对于提高开发效率和优化代码质量具有积极意义...
作为一种经典的文本关键字提取和摘要自动生成算法,TextRank将文本看做若干单词组成的集合,并通过对单词节点图的节点权值进行迭代计算,挖掘单词之间的潜在语义关系。在TextRank节点图模型的基础上,将马尔可夫状态...
本项目主要涉及两种查找算法:哈希查找(Hash Search)和二分查找(Binary Search),并且应用在统计C语言源文件中的关键字个数。下面将详细阐述这两种查找算法以及它们在本项目中的具体应用。 哈希查找是一种高效...
算法的输入通常是一个字符串类型的长篇文章(st)和一个待查找的关键字(key)。在案例中,关键字是从URL参数(Request.QueryString["KeyWord"])获取的。初始化一个正则表达式对象(reg),用于匹配关键字。 2. *...
综合查找算法课程设计报告书旨在通过实践加深对各种查找算法的理解和应用,这些算法在软件和硬件设计领域中起着至关重要的作用。本项目利用Java编程语言,借助Eclipse开发环境,实现了一个用户友好的图形界面,允许...
### 静态查找表与折半查找算法 在计算机科学中,静态查找表是一种用于存储数据并能够高效检索特定元素的数据结构。本篇文章将详细解释如何实现一个静态查找表,并利用折半查找算法(也称二分查找算法)来查询表中的...
查找算法的比较 在计算机科学中,查找算法是一种基本且常用的算法,它们的应用非常广泛。本文将对几种常用的查找算法进行比较,包括顺序查找、二分查找、二叉树查找和哈希表查找。 顺序查找是一个最简单的查找算法...
标题中的“电信设备-一种基于关键字查找信息的方法及系统”暗示了这是一份关于电信行业中信息检索技术的文档。在现代通信系统中,快速、准确地查找和处理信息是至关重要的,尤其是对于处理大量数据的电信设备而言。...