通过Trie

时间:2018-05-01 07:57:15

标签: python trie

我编写了一个实现Trie数据结构的代码,它接受一个字符串列表和字符串的计数。

lst = [['james',9],['chloe',20],['chlara',30]]

字符串是名称,后跟的整数值是计数。一旦构建了trie,它就会提示用户输入前缀

userinput = ch

这样,代码将返回字符串chlara,因为它与chloe相比具有更高的计数,而chloe也具有前缀ch。我已经设法构建了Trie,但我在搜索功能方面遇到了困难。

class Node:
    def __init__(self):
        self.children = [None] * 26
        self.end = False
        self.frequency = 0
        self.goindex = 0
        self.index = 0

class Trie:
    def __init__(self):
        self.root = Node()

    def ord_char(self,key):
        ord_rep = ord(key) - ord('a')
        return ord_rep

    def add_word(self,lst):
        word = lst[0]    #word
        freq = lst[1]    #frequency of string

        word_len = len(word)    

        current = self.root    #start from root node

        for i in range(word_len):
            position = self.ord_char(word[i])

            if current.children[position] is None:
                current.children[position] = Node()

            current = current.children[position]

            if current.frequency > freq:
                continue
            else:
                current.frequency = freq
            current.index = position

        current.end = True  #end of string


def main():
    trie = Trie()

    for i in list2:
        trie.add_word(i)
    user = input("Enter a prefix: ")
    print(trie.prefix_search(user))

if __name__ == "__main__":
    main()

我正在返回不完整的字符串'chla',我很确定这是因为我的搜索功能效率低下且无法正常工作。

更新

我现在面临的问题是,如果我的前缀是“异常”,我将被归为“异常”而不是“异常”

1 个答案:

答案 0 :(得分:1)

你永远不会正确地穿越你的特里。您有两个嵌套的Route::get('/landlordsonly', function () { return view('x'); })->middleware('can:manage,property'); 循环,因此只从您的前缀遍历另外两个节点(字符)。

我将假设你想要返回一个结果,即使有多个字符串具有匹配的后缀和匹配计数。

使用for循环,并保持跟随最高while值,直到到达一个节点,该节点没有更多子节点,其值等于当前节点的计数。请确认该节点count为True,因为这表示您的添加单词代码中存在错误:

end

演示:

def prefix_search(self, prefix):
    # traverse the prefix
    current = self.root
    for c in prefix:
        current = current.children[self.ord_char(c)]
        if current is None:
            return None  # None is a much better return value than -1

    while current is not None:
        for child in current.children:
            if child is None:
                continue
            if child.count == current.count:
                # found first child with same score, continue from here
                prefix += chr(child.index + 97)
                current = child
                break
        else:
            # no children with equal score, this is the longest match
            assert current.end, "Data structure inconsistent"
            return prefix

以及其中一些边缘案例:

>>> trie.prefix_search('ch')
'chlara'
>>> trie.prefix_search('j')
'james'

如果数据结构中有错误;故意设置错误的计数:

>>> trie.add_word(('chlarissa', 9))  # longer word, lower count!
>>> trie.prefix_search('ch')
'chlara'
>>> trie.add_word(('janet', 6))  # same length and score as james, won't be found
>>> trie.prefix_search('j')
'james'