Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/360.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
python中trie的高效部分搜索_Python_Python 3.x_Optimization_Trie - Fatal编程技术网

python中trie的高效部分搜索

python中trie的高效部分搜索,python,python-3.x,optimization,trie,Python,Python 3.x,Optimization,Trie,这是一个hackerrank练习,虽然问题本身已经解决了,但我的解决方案显然不够有效,所以在大多数测试用例中,我都会超时。问题是: 我们将制作自己的联系人应用程序!应用程序必须执行两种类型的操作: 添加姓名,其中姓名是表示联系人姓名的字符串。这必须作为新联系人存储在应用程序中。 find partial,其中partial是一个字符串,表示要在应用程序中搜索的部分名称。它必须从partial开始计算联系人数,并在新行上打印计数。 给定n个顺序添加和查找操作,按顺序执行每个操作。 我正在尝试让它工

这是一个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的搜索,这同样只是计算单词的后代节点的数量,从表示部分匹配的节点开始