基于 double array 实现汉字的trie树索引 与 查询功能 python实现
来源:互联网 发布:阿尔法猎手 软件 编辑:程序博客网 时间:2024/06/05 03:38
一、 基本原理。
基本原理:利用字符串集合中字符串的公共前缀来降低时间开销以达到提高效率的目的。
性质:1,根结点不包含任何字符信息;2,如果字符的种数为n(如英文的26个字母),则每个结点的出度为n(这样必然会导致浪费很多空间,这也是trie的缺点,我还没有想到好点的办法避免);3,查找,插入复杂度为O(n),n为字符串长度。
具体请百度之。
二、基于 trie字典的汉字串检索代码(python):
# coding=gbkdicts = ['啊','阿根廷','阿胶','阿拉伯','阿拉伯人','埃及']# 字后缀数组sufarr = {'啊':[],'阿':['根','胶','拉'],'埃':['及'], '根':['廷'],'胶':[],'拉':['伯'],'及':[], '廷':[],'伯':['人'],'人':[]}# 按ID编码codes = [ '啊','阿','埃','根','胶','拉','及','廷','伯','人' ]# 字的层次标示level = [1, 1, 1, 2, 2, 2, 2, 3, 3, 4]# 构建双数组base = [0]*21 # len:21 ; 21=2*10+1 的素数check = [0]*21# 记录已确定的字的base索引bid_mark = {'啊':0,'阿':1,'埃':2, '根':0,'胶':0,'拉':0,'及':0,'廷':0,'伯':0,'人':0}base[:3]=[1]*3 # 首字部分,简单置为1def pre_mark(pre_word,wi,word): ''' 判断base中wi下标的前缀都在pre_words词表直到首字 且word为wi下标对应的字 ''' bkeys = bid_mark.keys() if word not in bkeys or bid_mark[word]!=wi: # 当前字的base值不匹配 return False pre_wi = check[wi] # 逆序遍历base的前缀 pid = -1 # 逆序遍历字的前缀 while pre_wi!=0 and (-1)*pid<=len(pre_word): if pre_word[pid] not in bkeys or bid_mark[pre_word[pid]]!=pre_wi: return False pre_wi = check[pre_wi] pid -= 1 if (-1)*pid>len(pre_word): return True # 完成前缀的遍历 else: return Falsefor w in dicts: cw = [ w[i:i+2] for i in range(0,len(w),2) ] # 分割出字 for iid in range(1,len(cw)): par_w = cw[iid-1] # 字的前缀 iid_w = cw[iid] # 当前的字 par_id = codes.index(par_w) # 字的前缀的编码 wid = codes.index(iid_w) bval = bid_mark[par_w] #if iid_w=='及': print "ID: %d, word: %s, pre-wrod: %s, code: %d, pre-code: %d, pre-base:%d"%( # iid,iid_w,par_w,wid,par_id,bval) for wi in range(base[bval]+wid,21): # 遍历所有可能的base位置 # 找到其base-id,置位 p_mk = pre_mark(cw[:iid],wi,iid_w) print "TEST::pre_mark() base-id: %d, word: %s, result: %s"%(wi,iid_w,str(p_mk)) if p_mk: # 该词及其前缀部分已经设置值 break if (not base[wi] and not check[wi]): # 该位置未使用或吻合前缀 check[wi] = bval # 设置字的 base[] 值 for tval in range(1,21-wi): # 遍历所有可能的取值 flag = True for suf_w in sufarr[iid_w]: chi_id = codes.index(suf_w) # 字的后缀的编码 if base[tval+chi_id]!=0 or check[tval+chi_id]!=0: flag = False break # tval不满足child的base check 为0,再尝试其他值 if flag: base[wi] = tval # 成功,保存该base[] if wi==6 or wi==-1 or wi==9: print "ID: %d, word: %s, pre-word: %s, base: %d, base-val: %d, check: %d"%( iid,iid_w,par_w,wi,tval,check[wi]) break if not base[wi]: # 无合适的 base print "ERROR:: set %s's base[]" % iid_w exit(1) bid_mark[iid_w] = wi #; print "finnished one! %s=%d" % (iid_w,wi) break # base check均成功 if not base[wi]: print "ERROR:: get %s's position in base[]" % iid_w exit(2)# 修改词尾标志for w in bid_mark.keys(): if len(sufarr[w])==0: eid = bid_mark[w] base[eid] *= -1# 查询给定词 def next_check(wid, code): ''' 验证两个base[]索引id间是否有连接 ''' if code<0 or code>=len(codes): # 字编码无效 return False chiid = abs(base[wid])+code if check[chiid]!=wid: return False return Trueqw = dicts[1] ; # 查询词res = '' # 返回结果words=[ qw[w:w+2] for w in range(0,len(qw),2) ]head_bid = bid_mark[words[0]] ; res = ''.join(words[0])for w in words[1:]: cod = codes.index(w) if not next_check(head_bid,cod): print "word: %s no find!" % qw break head_bid = abs(base[head_bid])+cod # 更新id res = ''.join([res,w]) if base[head_bid]<0: print "find a word: %s in Search word: %s"%(res,qw)参考: http://blog.csdn.net/joylnwang/article/details/6825991
- 基于 double array 实现汉字的trie树索引 与 查询功能 python实现
- double-array trie算法实现
- QT实现Double-Array Trie
- Android用Double Array Trie (双数组)实现关键字的搜索
- Trie树python实现
- Trie树分析及其查询的实现
- Trie树(压缩Trie树及Double-Array Trie)
- 基于SceneControl单击查询功能的实现
- 飘逸的python - 实现trie树
- 支持中文的基于词为基本粒度的前缀树(prefix trie)python实现
- double array trie
- 什么是Double Array Trie
- 深入double array trie
- double array trie
- Double Array Trie
- Double Array Trie
- Double Array Trie
- Trie树 的理论与实现
- IOS开发相关资料
- 结构标记不能嵌套在内容标记?
- htmlpaser打造个性化的爬虫程序 第一天
- 自定义方法copy数组 和 Java类库对数组复制的支持
- iOS 编码规范
- 基于 double array 实现汉字的trie树索引 与 查询功能 python实现
- [转]如何使用lib,dll等文件
- Oracle 11gR2 crs_stat 命令不再显示instance信息
- @GeneratedValue
- 两个链表是否相交
- 堆的操作和实现
- Android样式化的定性对象--Style样式的定义
- myeclipse 优化
- Direct Tunnel in the GPRS