2018-07-08 23:28:29 +08:00
|
|
|
''' mbinary
|
|
|
|
#########################################################################
|
|
|
|
# File : trie.py
|
|
|
|
# Author: mbinary
|
|
|
|
# Mail: zhuheqin1@gmail.com
|
2019-01-31 12:09:46 +08:00
|
|
|
# Blog: https://mbinary.xyz
|
2018-07-08 23:28:29 +08:00
|
|
|
# Github: https://github.com/mbinary
|
|
|
|
# Created Time: 2018-05-19 23:06
|
|
|
|
# Description:
|
|
|
|
#########################################################################
|
|
|
|
'''
|
|
|
|
|
|
|
|
class node:
|
|
|
|
def __init__(self,val = None):
|
|
|
|
self.val = val
|
|
|
|
self.isKey = False
|
|
|
|
self.children = {}
|
|
|
|
def __getitem__(self,i):
|
|
|
|
return self.children[i]
|
|
|
|
def __iter__(self):
|
|
|
|
return iter(self.children.keys())
|
|
|
|
def __setitem__(self,i,x):
|
|
|
|
self.children[i] = x
|
|
|
|
def __bool__(self):
|
|
|
|
return self.children!={}
|
|
|
|
def __str__(self):
|
|
|
|
return 'val: '+str(self.val)+'\nchildren: '+' '.join(self.children.keys())
|
|
|
|
def __repr__(self):
|
|
|
|
return str(self)
|
|
|
|
|
|
|
|
class Trie(object):
|
|
|
|
|
|
|
|
def __init__(self):
|
|
|
|
self.root=node('')
|
|
|
|
self.dic ={'insert':self.insert,'startsWith':self.startsWith,'search':self.search}
|
|
|
|
|
|
|
|
def insert(self, word):
|
|
|
|
"""
|
|
|
|
Inserts a word into the trie.
|
|
|
|
:type word: str
|
|
|
|
:rtype: void
|
|
|
|
"""
|
|
|
|
if not word:return
|
|
|
|
nd = self.root
|
|
|
|
for i in word:
|
|
|
|
if i in nd:
|
|
|
|
nd = nd[i]
|
|
|
|
else:
|
|
|
|
newNode= node(i)
|
|
|
|
nd[i] = newNode
|
|
|
|
nd = newNode
|
|
|
|
else:nd.isKey = True
|
|
|
|
def search(self, word,matchAll='.'):
|
|
|
|
"""support matchall function eg, 'p.d' matchs 'pad' , 'pid'
|
|
|
|
"""
|
|
|
|
self.matchAll = '.'
|
|
|
|
return self._search(self.root,word)
|
|
|
|
def _search(self,nd,word):
|
|
|
|
for idx,i in enumerate(word):
|
|
|
|
if i==self.matchAll :
|
|
|
|
for j in nd:
|
|
|
|
bl =self._search(nd[j],word[idx+1:])
|
|
|
|
if bl:return True
|
|
|
|
else:return False
|
|
|
|
if i in nd:
|
|
|
|
nd = nd[i]
|
|
|
|
else:return False
|
|
|
|
else:return nd.isKey
|
|
|
|
def startsWith(self, prefix):
|
|
|
|
"""
|
|
|
|
Returns if there is any word in the trie that starts with the given prefix.
|
|
|
|
:type prefix: str
|
|
|
|
:rtype: bool
|
|
|
|
"""
|
|
|
|
nd = self.root
|
|
|
|
for i in prefix:
|
|
|
|
if i in nd:
|
|
|
|
nd= nd[i]
|
|
|
|
else:return False
|
|
|
|
return True
|
|
|
|
def display(self):
|
|
|
|
print('preOrderTraverse data of the Trie')
|
|
|
|
self.preOrder(self.root,'')
|
|
|
|
def preOrder(self,root,s):
|
|
|
|
s=s+root.val
|
|
|
|
if root.isKey:
|
|
|
|
print(s)
|
|
|
|
for i in root:
|
|
|
|
self.preOrder(root[i],s)
|
|
|
|
|
|
|
|
if __name__=='__main__':
|
|
|
|
t = Trie()
|
|
|
|
op = ["insert","insert","insert","insert","insert","insert","search","search","search","search","search","search","search","search","search","startsWith","startsWith","startsWith","startsWith","startsWith","startsWith","startsWith","startsWith","startsWith"]
|
|
|
|
data = [["app"],["apple"],["beer"],["add"],["jam"],["rental"],["apps"],["app"],["ad"],["applepie"],["rest"],["jan"],["rent"],["beer"],["jam"],["apps"],["app"],["ad"],["applepie"],["rest"],["jan"],["rent"],["beer"],["jam"]]
|
2018-07-11 19:26:24 +08:00
|
|
|
rsts = [None,None,None,None,None,None,False,True,False,False,False,False,False,True,True,False,True,True,False,False,False,True,True,True]
|
|
|
|
|
2018-07-08 23:28:29 +08:00
|
|
|
for i,datum,rst in zip(op,data,rsts):
|
|
|
|
if t.dic[i](datum[0]) != rst:print(i,datum[0],rst)
|
|
|
|
t.display()
|