Пример #1
0
        public ArgsTrie(IEnumerable <ArgsMap <TValue> > mappings, bool caseSensitive)
            : base(DefaultTrieWidth)
        {
            this.CaseSensitive = caseSensitive;

            // load trie
            foreach (ArgsMap <TValue> map in mappings)
            {
                TrieNode <char, TValue> node = this;

                string prefix = caseSensitive ? map.Prefix : map.Prefix.ToLowerInvariant();

                // build out the path for StartToken
                foreach (char ch in prefix)
                {
                    if (!node.Contains(ch))
                    {
                        node[ch] = new TrieNode <char, TValue>(DefaultTrieWidth);
                    }

                    node = (TrieNode <char, TValue>)node[ch];
                }

                // at the end of the Prefix is the Index
                node.Value = map.Index;
            }
        }
Пример #2
0
    /*
     * Finds the exact node that corresponds to a search query
     * returns null if node doesn't exist
     */
    public TrieNode?FindNode(string search)
    {
        bool     first   = true;
        TrieNode current = new TrieNode(' ');

        foreach (char c in search)
        {
            if (first)
            {
                first = false;
                if (roots.ContainsKey(c))
                {
                    current = roots[c];
                }
                else
                {
                    return(null);
                }
                continue;
            }

            if (current.Contains(c))
            {
                current = current.edges[c];
            }
            else
            {
                return(null);
            }
        }

        return(current);
    }
Пример #3
0
            private void BuildTrie(string v)
            {
                TrieNode current = _TrieNode;

                for (int i = 0; i < v.Length; i++)
                {
                    if (!current.Contains(v[i]))
                    {
                        current.Put(v[i], new TrieNode());
                    }
                    else
                    {
                        current = current.Child['a' - v[i]];
                    }
                }
                current.Word = v;
            }
Пример #4
0
    public string Search(string input)
    {
        string result = "";

        // maintain a stack of traversed nodes
        Stack <TrieNode> foundNodes = new Stack <TrieNode>();

        TrieNode currentNode = root;

        // for each character in a given input string
        foreach (char i in input)
        {
            // if not found at current traversal, stop search
            if (!currentNode.Contains(i, out currentNode))
            {
                break;
            }
            // found,
            foundNodes.Push(currentNode);
        }

        // because only the trie knows the termination of prefix strings
        //   we may have traversed a substring.
        // for example with given prefix '12' and '1234' and a input of '1234'
        //   we have a tree representation of 1-2(end)-3-4(end)
        //   we will have traverse to 1-2-3 and need to back-up to an ending node
        // remove any trailing non-terminating nodes (End is false)
        while (foundNodes.Count > 0 && !foundNodes.Peek().End)
        {
            foundNodes.Pop();
        }

        // concat value
        while (foundNodes.Count > 0)
        {
            currentNode = foundNodes.Pop();
            result      = currentNode.Value + result;
        }

        return(result);
    }
Пример #5
0
    public void Add(string item)
    {
        bool     first   = true;
        TrieNode current = new TrieNode(' ');

        foreach (char c in item.ToLower())
        {
            if (first)
            {
                current = roots[c];
                first   = false;
                continue;
            }

            if (!current.Contains(c))
            {
                current.Add(new TrieNode(c));
            }

            current = current.edges[c];
        }
    }
Пример #6
0
        public FilterTrie(IEnumerable <ReadFilter> filters) : base(DefaultTrieWidth)
        {
            // load trie
            foreach (ReadFilter filter in filters)
            {
                TrieNode <char, string> node = this;

                // build out the path for StartToken
                foreach (char ch in filter.StartToken)
                {
                    if (!node.Contains(ch))
                    {
                        node[ch] = new TrieNode <char, string>(DefaultTrieWidth);
                    }

                    node = (TrieNode <char, string>)node[ch];
                }

                // at the end of StartToken path is the EndToken
                node.Value = filter.EndToken;
            }
        }
Пример #7
0
 /** Returns if the word is in the trie. */
 public bool Search(string word)
 {
     return(treeRoot.Contains(word));
 }
Пример #8
0
        public void TestTrieNode()
        {
            var root = new TrieNode();

            Assert.AreEqual(1, root.NodeCount);
            Assert.AreEqual(0, root.WordCount);
            Assert.IsFalse(root.Contains(""));
            Assert.IsFalse(root.Contains("a"));
            root.Add("");
            Assert.AreEqual(1, root.NodeCount);
            Assert.AreEqual(1, root.WordCount);
            Assert.IsTrue(root.Contains(""));
            Assert.IsFalse(root.Contains("a"));
            root.Add("ab");
            Assert.AreEqual(3, root.NodeCount);
            Assert.AreEqual(2, root.WordCount);
            Assert.IsTrue(root.Contains(""));
            Assert.IsFalse(root.Contains("a"));
            Assert.IsFalse(root.Contains("ba"));
            Assert.IsTrue(root.Contains("ab"));
            root.Add("ac");
            Assert.AreEqual(4, root.NodeCount);
            Assert.AreEqual(3, root.WordCount);
            Assert.IsTrue(root.Contains(""));
            Assert.IsFalse(root.Contains("a"));
            Assert.IsTrue(root.Contains("ab"));
            Assert.IsTrue(root.Contains("ac"));
            root.Delete("ab");
            Assert.AreEqual(3, root.NodeCount);
            Assert.AreEqual(2, root.WordCount);
            Assert.IsTrue(root.Contains(""));
            Assert.IsFalse(root.Contains("a"));
            Assert.IsFalse(root.Contains("ab"));
            Assert.IsTrue(root.Contains("ac"));
            root.Delete("ac");
            Assert.AreEqual(1, root.NodeCount);
            Assert.AreEqual(1, root.WordCount);
            root.Delete("");
            Assert.AreEqual(1, root.NodeCount);
            Assert.AreEqual(0, root.WordCount);
        }
Пример #9
0
        /// <summary>
        /// Returns the collection of items similar to the word. This implementation was inspired by
        /// the following python implementation - https://github.com/teoryn/SpellCheck
        /// </summary>
        /// <param name="word">Word for which similar items should be found</param>
        /// <param name="maxDist">Maximum difference between strings (defined as edit distance)</param>
        /// <param name="node">Current trie node</param>
        /// <param name="built">The part which has been already built</param>
        /// <returns>The collection of items similar to the word</returns>
        public IEnumerable <string> FindSimilar(string word, int maxDist, TrieNode node, string built)
        {
            var result = new List <string>();

            if (maxDist < 0)
            {
                return(result);
            }

            if (node == null)
            {
                node = root;
            }

            var childNodes = node.GetAllChildren();

            // trying to insert every char for this trie node
            for (int i = 0; i < childNodes.Count(); i++)
            {
                if (childNodes[i] != null)
                {
                    result.AddRange(FindSimilar(word, maxDist - 1, childNodes[i], built + (char)(i + node.BaseChar)));
                }
            }

            // if there are no letters in word, then stop recursing
            if (string.IsNullOrEmpty(word))
            {
                if (node.IsEntry)
                {
                    result.Add(built);
                }

                return(result);
            }

            // if current trie node contains the first char of the word
            if (node.Contains(word[0]))
            {
                // then try to use it and do not perform any edit on this step
                result.AddRange(FindSimilar(word.Substring(1), maxDist, node.GetChild(word[0]), built + word[0]));
            }

            // This check lets us avoid unnecessary recursive calls
            if (maxDist == 0)
            {
                return(result);
            }

            // trying to remove the first char from the word
            result.AddRange(FindSimilar(word.Substring(1), maxDist - 1, node, built));

            // trying to replace the first char from the word with one of the chars from the current trie node
            for (int i = 0; i < childNodes.Count(); i++)
            {
                if (childNodes[i] != null && (char)(i + node.BaseChar) != word[0])
                {
                    result.AddRange(FindSimilar(word.Substring(1), maxDist - 1, childNodes[i], built + (char)(i + node.BaseChar)));
                }
            }

            // if the word is at least two chars long and the second char is contained in the current trie node
            if (word.Length > 1 && node.Contains(word[1]))
            {
                // then try to transpose the first and the seconds chars from the word
                result.AddRange(FindSimilar(word[0] + word.Substring(2), maxDist - 1, node.GetChild(word[1]), built + word[1]));
            }

            return(result);
        }