public PrefixTree(int maxDepth, string[] words, bool buildSuffix = false)
    {
        this.maxDepth = maxDepth + 1; // +1 because root is a "useless" node

        root = new PrefixTreeNode(' ');

        ConstructPrefixTree(words, buildSuffix);
    }
    private bool FindCombinationFromWord(string word, PrefixTreeNode root)
    {
        Stack <int> searchStringIdx = new Stack <int>();

        searchStringIdx.Push(0);

        while (searchStringIdx.Count > 0)
        {
            int idx = searchStringIdx.Pop();

            // Start traversing the PrefixTree until we find a word terminator node.
            PrefixTreeNode curr    = root;
            int            charIdx = idx;

            while (curr != null && charIdx < word.Length)
            {
                if (curr.terminatesWord)
                {
                    // We've found a word, so we should try searching again for
                    // the word ignoring the first charIdx chars in front.
                    // Unless we've also reached the end of the word...
                    if (charIdx != word.Length)
                    {
                        searchStringIdx.Push(charIdx);
                    }
                }

                // In either case, keep searching down until we reach a leaf node
                // (or cannot progress further).
                curr = curr.children.ContainsKey(word[charIdx]) ? curr.children[word[charIdx]] : null;

                // If curr isn't null we'll continue searching at the next charIdx.
                if (curr != null)
                {
                    charIdx++;
                }
            }

            // Did we reach a leaf node?
            if (charIdx == word.Length)
            {
                // Was this at least the second traversal for this word?
                // (This implies we've used two words to form this larger word)
                if (idx > 0)
                {
                    // Then we found a match!
                    return(true);
                }
            }
        }

        return(false);
    }
Example #3
0
        /// <summary>
        /// Build a tree from a list of words
        /// </summary>
        /// <param name="wordlist"></param>
        public void BuildTree(IEnumerable<string> wordlist)
        {
            // for each word in the list
            PrefixTreeNode child;
            foreach (var word in wordlist)
            {
                // if we don't have a child with the first character in the word, create one
                if (!children.TryGetValue(word[0], out child))
                {
                    child = new PrefixTreeNode(word[0]);
                    children.Add(word[0], child);
                }

                // insert the word, starting with the child
                child.InsertWord(word, 0);
            }
        }
    public IList <string> FindAllConcatenatedWordsInADict(string[] words)
    {
        List <string> results = new List <string>();

        if (words == null || words.Length == 0 || words.Length == 1)
        {
            return(results);
        }

        // First store every word into the prefix tree.
        PrefixTreeNode root         = new PrefixTreeNode();
        int            minStringLen = int.MaxValue;

        for (int i = 0; i < words.Length; i++)
        {
            root.AddWord(0, words[i]);

            // As an optimization, we'll store the minimum string length
            // that we see. This way, we know we only need to later test
            // against strings that are twice this size at minimum.
            minStringLen = Math.Min(minStringLen, words[i].Length);
        }

        minStringLen *= 2;

        // Now, what we want to do is consider a specialized PrefixTreeTraversal
        // of each string that meets out minStringLen requirements.
        foreach (string word in words)
        {
            if (word.Length < minStringLen)
            {
                continue;
            }

            bool found = FindCombinationFromWord(word, root);

            if (found)
            {
                results.Add(word);
            }
        }

        return(results);
    }
 static SyntaxToken()
 {
     OperatorsTree = new PrefixTreeNode();
     foreach (var op in ValidOperators)
     {
         var node = OperatorsTree;
         foreach (var letter in op)
         {
             PrefixTreeNode nextNode;
             if (node.Nodes.TryGetValue(letter, out nextNode))
                 node = nextNode;
             else
             {
                 nextNode = new PrefixTreeNode();
                 node.Nodes.Add(letter, nextNode);
                 node = nextNode;
             }
         }
     }
 }