如何利用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



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值