python中trie的高效部分搜索
这是一个hackerrank练习,虽然问题本身已经解决了,但我的解决方案显然不够有效,所以在大多数测试用例中,我都会超时。问题是: 我们将制作自己的联系人应用程序!应用程序必须执行两种类型的操作: 添加姓名,其中姓名是表示联系人姓名的字符串。这必须作为新联系人存储在应用程序中。 find partial,其中partial是一个字符串,表示要在应用程序中搜索的部分名称。它必须从partial开始计算联系人数,并在新行上打印计数。 给定n个顺序添加和查找操作,按顺序执行每个操作。 我正在尝试让它工作,下面是代码:python中trie的高效部分搜索,python,python-3.x,optimization,trie,Python,Python 3.x,Optimization,Trie,这是一个hackerrank练习,虽然问题本身已经解决了,但我的解决方案显然不够有效,所以在大多数测试用例中,我都会超时。问题是: 我们将制作自己的联系人应用程序!应用程序必须执行两种类型的操作: 添加姓名,其中姓名是表示联系人姓名的字符串。这必须作为新联系人存储在应用程序中。 find partial,其中partial是一个字符串,表示要在应用程序中搜索的部分名称。它必须从partial开始计算联系人数,并在新行上打印计数。 给定n个顺序添加和查找操作,按顺序执行每个操作。 我正在尝试让它工
import re
def add_contact(dictionary, contact):
_end = '_end_'
current_dict = dictionary
for letter in contact:
current_dict = current_dict.setdefault(letter, {})
current_dict[_end] = _end
return(dictionary)
def find_contact(dictionary, contact):
p = re.compile('_end_')
current_dict = dictionary
for letter in contact:
if letter in current_dict:
current_dict = current_dict[letter]
else:
return(0)
count = int(len(p.findall(str(current_dict))) / 2)
re.purge()
return(count)
n = int(input().strip())
contacts = {}
for a0 in range(n):
op, contact = input().strip().split(' ')
if op == "add":
contacts = add_contact(contacts, contact)
if op == "find":
print(find_contact(contacts, contact))
因为这个问题不需要返回partial是否匹配,而是要计算匹配它的所有条目,所以我找不到其他方法,只能将嵌套字典转换为一个字符串,然后计算所有的_end,我用它来表示存储的字符串。这似乎是罪魁祸首,但我找不到更好的方法进行搜索。我如何使这项工作更快?提前谢谢
UPD:
我添加了一个实际解析树的结果计数器,但是代码对于在线检查器来说仍然太慢。有什么想法吗
def find_contact(dictionary, contact):
current_dict = dictionary
count = 0
for letter in contact:
if letter in current_dict:
current_dict = current_dict[letter]
else:
return(0)
else:
return(words_counter(count, current_dict))
def words_counter(count, node):
live_count = count
live_node = node
for value in live_node.values():
if value == '_end_':
live_count += 1
if type(value) == type(dict()):
live_count = words_counter(live_count, value)
return(live_count)
好的,所以,事实证明,使用嵌套dict通常不是一个好主意,因为hackerrank会将100k字符串塞进你的程序,然后一切都会变得缓慢。所以问题不在解析中,而是在解析之前的存储中。最终我发现,他们的解决方案100%通过了挑战。以下是完整的代码:
class Node:
def __init__(self):
self.count = 1
self.children = {}
trie = Node()
def add(node, name):
for letter in name:
sub = node.children.get(letter)
if sub:
sub.count += 1
else:
sub = node.children[letter] = Node()
node = sub
def find(node, data):
for letter in data:
sub = node.children.get(letter)
if not sub:
return 0
node = sub
return node.count
if __name__ == '__main__':
n = int(input().strip())
for _ in range(n):
op, param = input().split()
if op == 'add':
add(trie, param)
else:
print(find(trie, param))
可能您正在查找匹配的子代数。。。你知道,穿过这棵树和所有的…。@juanpa.arrivillaga,这正是我要找的。我只是不知道如何做的足够有效。你知道如何搜索一棵树吗?关于这一主题,可能有数以百万计的教程,CS人对树木着迷。我的意思是,你似乎对trie很熟悉,所以我猜你在什么地方有这个想法。从节点开始遍历树,计算匹配的子节点数。从您的表示中生成字符串并使用正则表达式只是。。。奇怪的你最好保留一份匹配的列表。或者是一个包含所有匹配项的大字符串。类似于的东西可能会在这里派上用场,尽管我不相信这个特定的函数可以工作dicts@DavidZ我很确定这个问题的核心是实现一个基于trie的搜索,这同样只是计算单词的后代节点的数量,从表示部分匹配的节点开始