当前位置: 首页 > 知识库问答 >
问题:

如何在TRIE中找到最长的弦

容鸿畴
2023-03-14

我已经用两个类实现了一个DS Trie:Trie和TrieNode。我需要编写一个函数,返回在O(h)中Trie中最长的字符串。我的TrieNode有一个字段LinkedList,它存储每个节点的子节点。我们还没有了解到BFS或DFS,所以我正在努力思考一些创造性的方法来解决它。

我已经有了一个函数(一个单独的函数),它通过给定的char插入/创建一个新节点:在构建trie时:创建一个节点,该节点的字段'maxdepth=0'指示我当前的深度。对于我创建的每个新节点,我将一直迭代到他的父节点(每个节点已经有一个指向他的父节点的指针),依此类推,直到我到达根节点,并将他的父节点的深度增加1。现在我将创建返回最长字符串的函数:对于每个节点:遍历我的子节点,查找最大整数'max depth‘而不是向下。这样做,直到您达到'maxdepth==0'。例如,我的算法可以很好地处理这个字符串:“AACGACE”

       root      
       / \
   (2)a   g(0)     
     / 
 (1)c        
   / 
(0)e     

=>ACE实际上是最长的。但对这个字符串不起作用:“Aacgae”

      root      
      /  \
   (2)a   g(0)     
    /  \
 (0)c  (0)e      

一般来说,我试图利用创建Trie的第一个函数(运行时间:O(H*C)),因此第二个函数(返回最长字符串)的运行时间将会更少。O(h)

共有1个答案

文嘉禧
2023-03-14

不确定你真正想做什么,但你可以在这里找到一个trie的例子。

基本上,我通过一个建设者来创建trie;让我们来简单介绍一下如何将一个单词添加到trie中:

// In TrieBuilder
final TrieNodeBuilder nodeBuilder = new TrieNodeBuilder();

// ...

/**
 * Add one word to the trie
 *
 * @param word the word to add
 * @return this
 * @throws IllegalArgumentException word is empty
 */
public TrieBuilder addWord(@Nonnull final String word)
{
    Objects.requireNonNull(word);

    final int length = word.length();

    if (length == 0)
        throw new IllegalArgumentException("a trie cannot have empty "
            + "strings (use EMPTY instead)");
    nrWords++;
    maxLength = Math.max(maxLength, length);
    nodeBuilder.addWord(word);
    return this;
}

这推迟了将单词添加到TrieNodeBuilder中的时间,后者执行以下操作:

private boolean fullWord = false;

private final Map<Character, TrieNodeBuilder> subnodes
    = new TreeMap<>();

TrieNodeBuilder addWord(final String word)
{
    doAddWord(CharBuffer.wrap(word));
    return this;
}

/**
 * Add a word
 *
 * <p>Here also, a {@link CharBuffer} is used, which changes position as we
 * progress into building the tree, character by character, node by node.
 * </p>
 *
 * <p>If the buffer is "empty" when entering this method, it means a match
 * must be recorded (see {@link #fullWord}).</p>
 *
 * @param buffer the buffer (never null)
 */
private void doAddWord(final CharBuffer buffer)
{
    if (!buffer.hasRemaining()) {
        fullWord = true;
        return;
    }

    final char c = buffer.get();
    TrieNodeBuilder builder = subnodes.get(c);
    if (builder == null) {
        builder = new TrieNodeBuilder();
        subnodes.put(c, builder);
    }
    builder.doAddWord(buffer);
}
    null

现在,如果我们添加“麻烦”,将在“E”之后为“S”创建另一个节点。

fullword变量告诉我们这里是否有潜在的完全匹配;下面是搜索函数:

public final class Trie
{
    private final int nrWords;
    private final int maxLength;
    private final TrieNode node;

    // ...

    /**
     * Search for a string into this trie
     *
     * @param needle the string to search
     * @return the length of the match (ie, the string) or -1 if not found
     */
    public int search(final String needle)
    {
        return node.search(needle);
    }
    // ...
}

Trienode中,我们有:

public final class TrieNode
{
    private final boolean fullWord;

    private final char[] nextChars;
    private final TrieNode[] nextNodes;

    // ...

    public int search(final String needle)
    {
        return doSearch(CharBuffer.wrap(needle), fullWord ? 0 : -1, 0);
    }

    /**
     * Core search method
     *
     * <p>This method uses a {@link CharBuffer} to perform searches, and changes
     * this buffer's position as the match progresses. The two other arguments
     * are the depth of the current search (ie the number of nodes visited
     * since root) and the index of the last node where a match was found (ie
     * the last node where {@link #fullWord} was true.</p>
     *
     * @param buffer the charbuffer
     * @param matchedLength the last matched length (-1 if no match yet)
     * @param currentLength the current length walked by the trie
     * @return the length of the match found, -1 otherwise
     */
    private int doSearch(final CharBuffer buffer, final int matchedLength,
        final int currentLength)
    {
        /*
         * Try and see if there is a possible match here; there is if "fullword"
         * is true, in this case the next "matchedLength" argument to a possible
         * child call will be the current length.
         */
        final int nextLength = fullWord ? currentLength : matchedLength;


        /*
         * If there is nothing left in the buffer, we have a match.
         */
        if (!buffer.hasRemaining())
            return nextLength;

        /*
         * OK, there is at least one character remaining, so pick it up and see
         * whether it is in the list of our children...
         */
        final int index = Arrays.binarySearch(nextChars, buffer.get());

        /*
         * If not, we return the last good match; if yes, we call this same
         * method on the matching child node with the (possibly new) matched
         * length as an argument and a depth increased by 1.
         */
        return index < 0
            ? nextLength
            : nextNodes[index].doSearch(buffer, nextLength, currentLength + 1);
    }
}

注意,在doSearch()的第一次调用中,-1是如何作为“NextLength”参数传递的。

    null
    null
 类似资料:
  • 如果我正确地看到了这一点,那么trie中的所有叶节点都将拼写出整个单词,所有父节点都包含最终叶节点之前的字符。因此,如果我有一个名为DigitalTreeNode的类,其定义为 如果我想实现一个返回trie中最长单词的方法,是否只需要在每个叶节点查找最长单词?如何实现方法,例如: 我猜它涉及到设置一个最长的字符串变量,递归地遍历每个节点,并检查它是否是一个单词,如果它是一个单词,并且它的长度大于最

  • 我们得到了表格的邻接列表 意味着从U到V有一个成本C的优势。 给定的邻接列表适用于具有N个节点的单连通树,因此包含N-1条边。 给出了一组节点。 现在的问题是,在F中的节点中找到最长路径的最佳方法是什么?可以用O(N)来做吗? 来自F中每个节点的DFS是唯一的选项吗?

  • 我有一个一般性的问题,关于如何在边没有权的无向图中找到最短路径和最长路径。 我们需要使用DFS算法来寻找图中的最长路径,而我们需要使用BFS算法来寻找图中的最短路径,这是一个正确的结论吗?

  • 我正在写一个程序,使用扫描仪的方法读取文本文件,并输出:字数,句子数,平均每个句子的字数,最长的句子和最短的句子。到目前为止,除了最长和最短的句子,我什么都知道了,我似乎想不出来。这是我目前所掌握的... 如果有人能帮上忙,我将感激不尽!!

  • 如何找到字符串的长度(字符串中的字符数),而不在R中拆分它?我知道如何计算列表的长度,但不知道字符串的长度。 Unicode字符串呢?如何查找Unicode字符串中的长度(以字节为单位)和字符数(符文、符号)? 相关问题: 如何在R中查找Unicode字符串中的“真实”字符数

  • 我在一个文本文件中有一个长字符串(DNA序列,超过20000个字符),我试图找到其中最长的序列,它至少重复了三次。实现这一目标的最佳方式是什么? 我能找到的唯一现有主题是在两个或多个单独的字符串中查找重复,但是如何使用一个长字符串?