如何利用trie树加快关键词查找
2017-08-08 19:33
381 查看
项目中有如下需求,给定一个关键词库(规模不定,从几百到几千不等),需要在一句话或者一段内容中快速找出关键词,如果有任何一个关键词命中就可以直接返回。
1. 简单的方法就是依次判断每个词是否存在于给定内容中:
该方式显然时间复杂度上不符合要求。
2. 可以使用trie树类似单字索引的方式来加速查找,使用trie查找关键词。
trie树结果上是一颗前缀树,某个节点的所有子孙都拥有相同的前缀,从根节点到叶子节点的一条路径可以认为是一个关键词。
#!/usr/bin/env python
#coding: utf-8
#author: wenhui
import os
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
import json
class Trie(object):
def __init__(self,logger=None,rfile=None):
self.data = {'ref':{}}
if logger:self.logger = logger
if rfile:
self.load(rfile)
self.max_word_size = 0
self.word_num = 0
def add(self, word):
ref = self.data['ref']
for char in word:
if char not in ref:
ref[char] = {}
ref = ref[char]
ref['\3'] = True
if len(word) > self.max_word_size:
self.max_word_size = len(word)
self.word_num += 1
def find(self,content):
ret = []
ref = self.data['ref']
content_size = len(content)
for idx,char in enumerate(content):
if not ref.has_key(char):continue
tmp_word_size,tmp_ref = 1,ref[char]
while tmp_word_size <= self.max_word_size:
if tmp_ref.get("\3",False):
return True,content[idx:idx+tmp_word_size]
if idx + tmp_word_size >= content_size:
break
tmp_char = content[idx+tmp_word_size]
if tmp_char not in tmp_ref:
break
tmp_word_size += 1
tmp_ref = tmp_ref[tmp_char]
return False,None
def load(self,rfile):
if not os.path.exists(rfile):
return False
try:
self.data = json.loads(open(rfile).read())
except Exception as e:
if self.logger:
self.logger.warn("trie load error\t%s" % str(e))
self.data = {'ref':{}}
return False
return True
def dump(self,rfile):
json.dump(self.data,open(rfile,"w"),ensure_ascii=False)
if __name__ == "__main__":
inst = Trie()
inst.add(u'主播')
print json.dumps(inst.data,ensure_ascii=False)
code,word = inst.find(u'标题: 韩国女主播青草女主播学生装热舞(9)')
print code,word
find方法可以快速放回第一个命中的关键词,时间复杂度为length(content)。
ref:https://zh.wikipedia.org/wiki/Trie
1. 简单的方法就是依次判断每个词是否存在于给定内容中:
def filter(content): for filter_word in filter_words: if filter_word in content: return True return False
该方式显然时间复杂度上不符合要求。
2. 可以使用trie树类似单字索引的方式来加速查找,使用trie查找关键词。
trie树结果上是一颗前缀树,某个节点的所有子孙都拥有相同的前缀,从根节点到叶子节点的一条路径可以认为是一个关键词。
#!/usr/bin/env python
#coding: utf-8
#author: wenhui
import os
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
import json
class Trie(object):
def __init__(self,logger=None,rfile=None):
self.data = {'ref':{}}
if logger:self.logger = logger
if rfile:
self.load(rfile)
self.max_word_size = 0
self.word_num = 0
def add(self, word):
ref = self.data['ref']
for char in word:
if char not in ref:
ref[char] = {}
ref = ref[char]
ref['\3'] = True
if len(word) > self.max_word_size:
self.max_word_size = len(word)
self.word_num += 1
def find(self,content):
ret = []
ref = self.data['ref']
content_size = len(content)
for idx,char in enumerate(content):
if not ref.has_key(char):continue
tmp_word_size,tmp_ref = 1,ref[char]
while tmp_word_size <= self.max_word_size:
if tmp_ref.get("\3",False):
return True,content[idx:idx+tmp_word_size]
if idx + tmp_word_size >= content_size:
break
tmp_char = content[idx+tmp_word_size]
if tmp_char not in tmp_ref:
break
tmp_word_size += 1
tmp_ref = tmp_ref[tmp_char]
return False,None
def load(self,rfile):
if not os.path.exists(rfile):
return False
try:
self.data = json.loads(open(rfile).read())
except Exception as e:
if self.logger:
self.logger.warn("trie load error\t%s" % str(e))
self.data = {'ref':{}}
return False
return True
def dump(self,rfile):
json.dump(self.data,open(rfile,"w"),ensure_ascii=False)
if __name__ == "__main__":
inst = Trie()
inst.add(u'主播')
print json.dumps(inst.data,ensure_ascii=False)
code,word = inst.find(u'标题: 韩国女主播青草女主播学生装热舞(9)')
print code,word
find方法可以快速放回第一个命中的关键词,时间复杂度为length(content)。
ref:https://zh.wikipedia.org/wiki/Trie
相关文章推荐
- 如何利用热播电视剧关键词引流?
- 如何加快按生产订单查找物料凭证的报表的速度
- 利用Trie树,来查找单词出现的次数
- 如何写出正确的二分查找?——利用循环不变式理解二分查找及其变体的正确性以及构造方式
- 如何写出正确的二分查找?——利用循环不变式理解二分查找及其变体的正确性以及构造方式
- 在Oracle中如何利用Rowid查找和删除表中的重复记录(转)
- 如何查找网站漏洞文件任意查看漏洞详情与利用
- 关于如何查找和利用PCL库学习资源的一些心得
- 在Oracle中如何利用Rowid查找和删除表中的重复记录
- 如何加快按生产订单查找物料凭证的报表的速度
- Java利用反射如何查找使用指定注解的类详解
- 如何利用锚文本来优化关键词
- 如何利用kettle官方社区查找关于carte服务的设置
- 如何利用IP标识查找网络风暴
- 如何利用QQ空间做关键词排名
- 在Oracle中如何利用Rowid查找和删除表中的重复记录
- 如何加快按生产订单查找物料凭证的报表的速度
- 如何写出正确的二分查找?——利用循环不变式理解二分查找及其变体的正确性以及构造方式
- 如何利用RamDisk加快上网速度
- 如何用SQL Server JOIN加快范围查找