采用DAWG方式在大批量字符串中查询字符串
最近在一个项目中需要针对上百万条(大约在800W条)的字符串进行相关的处理。该字符串是以文本的形式存放在本地硬盘,并且更新频率为20分钟一次。
具体需求:
1、判断某一个字符串是否存在这800W条字符串中,时间要求在5ms以内
2、根据字符串前缀,返回包含此前缀的10-100条字符串。时间要求在5ms以内
3、占用内存要小
本人接到此需求第一反应用List,或者二叉树啥的。结果效率慢得死,
后经过大量资料查阅,发现采用DAWG(Directed Acyclic Word Graph)和Trie可以很快速的查找到相应的字符串。
主要思路:将每个字符串的字符进行创建相应的Node,如果有相同的字符则放置在同一个节点中。
例如有6个字符串:Top, Tops, Tap, Tapc, Topa and Taps。根据DAWG和Trie的原理将创建成如下一个Tree
在添加字符串的时候,根据字符串的字符创建树形结构,每个节点代表一个字符。如果是相同字符时,则存储在同一个节点中。这样可少占用内存。
在进行判断字符串是否存在时,只需要依次判断字符串的节点是否存在。
首先创建一个字符节点类LetterNode. 该类主要用于存储相关字符节点的信息:子节点,父节点等等。
/// The Dawg's letter node
/// </summary>
internal sealed class LetterNode
{
private const int InitialSpreadCapacity = 4;
private Dictionary<char, LetterNode> _childNodes;
/// <summary>
/// Initializes a new instance of the <see cref="LetterNode"/> class.
/// </summary>
public LetterNode()
{
}
/// <summary>
/// Initializes a new instance of the <see cref="LetterNode"/> class.
/// </summary>
/// <param name="letter">The letter.</param>
public LetterNode(char letter)
: this()
{
Letter = letter;
}
/// <summary>
/// The node's child nodes
/// </summary>
public Dictionary<char, LetterNode> ChildNodes
{
get
{
if (this._childNodes == null)
{
this._childNodes = new Dictionary<char, LetterNode>(InitialSpreadCapacity);
}
return this._childNodes;
}
}
/// <summary>
/// Describe the node is end of the word.
/// </summary>
public bool IsEndOfWord
{
get;
set;
}
/// <summary>
/// Gets or sets the letter.
/// </summary>
/// <value>The letter.</value>
public char Letter
{
get;
set;
}
/// <summary>
/// Gets or sets the parent of this node.
/// </summary>
/// <value>The parent.</value>
public LetterNode Parent
{
get;
set;
}
/// <summary>
/// Gets the word defined at this element.
/// </summary>
/// <value>The word ending here (if this is a word, or the empty string.</value>
public string Word
{
get
{
if (IsEndOfWord)
{
StringBuilder sb = new StringBuilder(20);
sb.Append(Letter);
var node = Parent;
while (node != null)
{
sb.Insert(0, node.Letter);
node = node.Parent;
}
return sb.ToString();
}
else
{
return string.Empty;
}
}
}
}
接下来实现Dawg针对字符串创建树形节点。思路是参照上图。
/// Adds the specified item.
/// </summary>
/// <param name="item">The item.</param>
public void Add(string item)
{
if (string.IsNullOrEmpty(item))
{
return;
}
item = item.ToLowerInvariant();
LetterNode node = null, parentNode = null;
if (!this._rootNodes.TryGetValue(item[0], out node))
{
node = new LetterNode(item[0]);
this._rootNodes[item[0]] = node;
}
for (int i = 1; i < item.Length; ++i)
{
parentNode = node;
if (!node.ChildNodes.TryGetValue(item[i], out node))
{
node = new LetterNode(item[i]);
node.Parent = parentNode;
parentNode.ChildNodes[item[i]] = node;
}
}
if (!node.IsEndOfWord)
{
node.IsEndOfWord = true;
this._count++;
}
}
判断字符串是否存在:
{
prefix = prefix.ToLowerInvariant();
Dictionary<char, LetterNode> nodes = this._rootNodes;
LetterNode node = null;
for (int i = 0; i < prefix.Length; ++i)
{
if (nodes.TryGetValue(prefix[i], out node))
{
nodes = node.ChildNodes;
}
else
{
return null;
}
}
return node;
}
{
var node = this.SearchPrefixLetterNode(item);
return node != null && node.IsEndOfWord;
}
代码可从此处下载:http://files.cnblogs.com/foolishfox/Dawg.zip
转载于:https://www.cnblogs.com/foolishfox/archive/2011/07/13/2105405.html
采用DAWG方式在大批量字符串中查询字符串相关推荐
- 如何用js获取浏览器URL中查询字符串的参数
首先要知道Location这个对象以及这个对象中的一些属性: href:设置或返回完整的url.如本博客首页返回http://www.cnblogs.com/wymninja/ host:设置或返回主 ...
- flask带有传入参数既有URL还有其他参数类型:建议使用方式二(flask 使用查询字符串的方式)
方式一: 例如此时,既需要传递带有URL的训练数据地址,还需要传入其他的参数 由于path类型会将所有的 / 不忽略,那么此时的 traget_cls 参数会被忽略,于是我们将带有URL的参数(即pa ...
- php 字符串中插入字符,PHP字符串中插入子字符串方法总结[原创]_php技巧
本文实例讲述了PHP字符串中插入子字符串方法.分享给大家供大家参考,具体如下: 首先来看看一个网上常见的方法: 方法一:字符串遍历 function str_insert($str, $i, $sub ...
- Java案例——统计字符串中每个字符串出现的次数
统计字符串中每个字符串出现的次数 需求: 1.键盘录入一个字符串,要求统计字符串中每个字符串出现的次数 举例:键盘录入"aababcabcdabcde" 在控制台输出:" ...
- 查找两个字符串中相同字符串_使两个字符串相同的最低成本
查找两个字符串中相同字符串 Problem statement: 问题陈述: Given two strings string1 and string2 find the minimum cost r ...
- hiho1482出勤记录II(string类字符串中查找字符串,库函数的应用)
string类中有很多好用的函数,这里介绍在string类字符串中查找字符串的函数. string类字符串中查找字符串一般可以用: 1.s.find(s1)函数,从前往后查找与目标字符串匹配的第一个位 ...
- URL 中,查询字符串与HTML实体冲突,可能带来的问题.
此问题相关信息(我不放在最前面,似乎有些朋友会找不到的样子.) IE10+, Safari5.17+, Firefox4.0+,Opera12+, Chrome7+ 已经按新标准实现. 所以就没有这个 ...
- Elasticsearch:使用新的 wildcard 字段更快地在字符串中查找字符串 - 7.9 新功能
在 Elasticsearch 7.9 中,我们将引入一种新的 "wildcard" 字段类型,该字段类型经过优化,可在字符串值中快速查找模式.这种新的字段类型采用了一种全新的方式 ...
- php 查字符串,PHP查询字符串技巧分享
对于一个经验丰富的PHP程序员来说,实现字符串的查询功能已经不是什么难事了.在这里我们将会介绍一种PHP查询字符串的捷径技巧,供大家参考. RL传递变量对于程序员来说已经是司空见惯的事情,很多人会因此 ...
最新文章
- [二叉树] 判断一个二叉树是否是平衡(剑指offer39)
- java数据生成excel_Java 数据库数据生成Excel
- 下载的java游戏怎么运行不了_java运行环境下载
- python语句分为_python以什么划分语句块
- 密码学专题 非对称加密算法指令概述 DSA算法指令
- ltspice 双脉冲_焊烟脉冲布袋式除尘器制作
- signature=0727ee8cc38ba70036807ebbc0b018d6,NMSSM+
- 鸿蒙app安卓版包,支付宝鸿蒙版本下载-支付宝鸿蒙app最新版 v10.2.8.7000-优盘手机站...
- 斯诺登:澳大利亚的监视政策比NSA还下流
- GCC 编译安装在线文档
- 动易2007后台模板上传任意文件漏洞
- Linux 串口驱动 问题
- 动态规划算法——2020美团校招合并金币算法
- 科学家学习天竺葵特性,研制出用水分子来驱动的微型机器人
- 极致Review,阿里绩效管理的核心工具
- 造成BGA焊接不良问题有哪些?
- 对于爱情的透彻性理解:恋爱变成一场无间道...
- PHP检测及判断手机登录用户是安卓或爱疯(iPhone)客户端
- WWDC 2020 特别活动主题演讲 全套源文件下载 视频、幻灯片图片、中英文全稿 WWDC 2020 Special Event Keynote
- Python编程(0-1)——Eric6界面初识
热门文章
- python 英语分词_英文分词算法(Porter stemmer)
- java环境变量win7_win7如何配置jdk环境变量|win7配置java环境变量的方法
- 计算机硬件 软件指什么,什么叫软件,什么又叫硬件呀?(是电脑知识)
- python socket发包_python 多线程tcp udp发包 Dos工具。
- 【筛法求素数】HDU-1239 Calling Extraterrestrial Intelligence Again
- 不知道起什么标题 03
- 在中文版Windows 10 中安装日语支持
- 纸牌博弈问题 动态规划
- VTK:数据动画用法实战
- Apollo坐标系转换