Exemple #1
0
        public override TrieNodeBase AddChild(char c, ref int node_count)
        {
            if (nodes == null)
            {
                m_base = c;
                nodes  = new TrieNodeBase[1];
            }
            else if (c >= m_base + nodes.Length)
            {
                Array.Resize(ref nodes, c - m_base + 1);
            }
            else if (c < m_base)
            {
                Char           c_new = (Char)(m_base - c);
                TrieNodeBase[] tmp   = new TrieNodeBase[nodes.Length + c_new];
                nodes.CopyTo(tmp, c_new);
                m_base = c;
                nodes  = tmp;
            }

            TrieNodeBase node = nodes[c - m_base];

            if (node == null)
            {
                node = new TrieNode();
                node_count++;
                nodes[c - m_base] = node;
            }
            return(node);
        }
Exemple #2
0
        /// <summary>
        /// Debug only; this is hideously inefficient
        /// </summary>
        public string GetKey(TrieNodeBase seek)
        {
            var sofar = string.Empty;

            GetKeyHelper fn = null;

            fn = cur =>
            {
                sofar += " ";   // placeholder
                foreach (var kvp in cur.CharNodePairs())
                {
                    //Util.SetStringChar(ref sofar, sofar.Length - 1, kvp.Key);
                    if (kvp.Value == seek)
                    {
                        return(true);
                    }
                    if (kvp.Value.Nodes != null && fn(kvp.Value))
                    {
                        return(true);
                    }
                }
                sofar = sofar.Substring(0, sofar.Length - 1);
                return(false);
            };

            if (fn(Root))
            {
                return(sofar);
            }
            return(null);
        }
Exemple #3
0
 public override void ReplaceChild(Char c, TrieNodeBase n)
 {
     if (nodes == null || c >= m_base + nodes.Length || c < m_base)
     {
         throw new Exception();
     }
     nodes[c - m_base] = n;
 }
Exemple #4
0
 public void OptimizeSparseNodes()
 {
     if (Root.ShouldOptimize)
     {
         Root = new SparseTrieNode(Root.CharNodePairs());
         c_sparse_nodes++;
     }
     Root.OptimizeChildNodes();
 }
Exemple #5
0
        public TValue ContainsKey(String s_in)
        {
            TrieNodeBase node = FindNode(s_in);

            if (node == null || !node.HasValue())
            {
                return(default(TValue));
            }
            return(node.Value);
        }
Exemple #6
0
    public IEnumerable <TrieNodeBase> SubsumedNodes(String s)
    {
        TrieNodeBase node = FindNode(s);

        if (node == null)
        {
            return(Enumerable.Empty <TrieNodeBase>());
        }
        return(node.SubsumedNodes());
    }
Exemple #7
0
    public TrieNodeBase Add(String s, TValue v)
    {
        TrieNodeBase node = _root;

        foreach (Char c in s)
        {
            node = node.AddChild(c, ref c_nodes);
        }

        node.Value = v;
        return(node);
    }
Exemple #8
0
    public TrieNodeBase FindNode(String s_in)
    {
        TrieNodeBase node = _root;

        foreach (Char c in s_in)
        {
            if ((node = node[c]) == null)
            {
                return(null);
            }
        }
        return(node);
    }
Exemple #9
0
    public bool Contains(String s)
    {
        TrieNodeBase node = _root;

        foreach (Char c in s)
        {
            node = node[c];
            if (node == null)
            {
                return(false);
            }
        }
        return(node.HasValue);
    }
Exemple #10
0
    public unsafe TValue Find(Char *p_tag, int cb_ctag)
    {
        TrieNodeBase node  = _root;
        Char *       p_end = p_tag + cb_ctag;

        while (p_tag < p_end)
        {
            if ((node = node[*p_tag]) == null)
            {
                return(default(TValue));
            }
            p_tag++;
        }
        return(node.Value);
    }
Exemple #11
0
    public IEnumerable <TValue> FindAll(String s_in)
    {
        TrieNodeBase node = _root;

        foreach (Char c in s_in)
        {
            if ((node = node[c]) == null)
            {
                break;
            }
            if (node.Value != null)
            {
                yield return(node.Value);
            }
        }
    }
Exemple #12
0
 /// <summary>
 /// Note: doesn't de-optimize optimized nodes if re-run later
 /// </summary>
 public void OptimizeChildNodes()
 {
     if (Nodes != null)
     {
         foreach (var q in CharNodePairs())
         {
             TrieNodeBase n_old = q.Value;
             if (n_old.ShouldOptimize)
             {
                 TrieNodeBase n_new = new SparseTrieNode(n_old.CharNodePairs());
                 n_new.m_value = n_old.m_value;
                 Trie <TValue> .c_sparse_nodes++;
                 ReplaceChild(q.Key, n_new);
             }
             n_old.OptimizeChildNodes();
         }
     }
 }
Exemple #13
0
    /// <summary>
    /// If continuation from the terminal node is possible with a different input string, then that node is not
    /// returned as a 'last' node for the given input. In other words, 'last' nodes must be leaf nodes, where
    /// continuation possibility is truly unknown. The presense of a nodes array that we couldn't match to
    /// means the search fails; it is not the design of the 'OrLast' feature to provide 'closest' or 'best'
    /// matching but rather to enable truncated tails still in the context of exact prefix matching.
    /// </summary>
    public TrieNodeBase FindNodeOrLast(String s_in, out bool f_exact)
    {
        TrieNodeBase node = _root;

        foreach (Char c in s_in)
        {
            if (node.IsLeaf)
            {
                f_exact = false;
                return(node);
            }
            if ((node = node[c]) == null)
            {
                f_exact = false;
                return(null);
            }
        }
        f_exact = true;
        return(node);
    }
Exemple #14
0
    // even though I found some articles that attest that using a foreach enumerator with arrays (and Lists)
    // returns a value type, thus avoiding spurious garbage, I had already changed the code to not use enumerator.
    public unsafe TValue Find(String s_in)
    {
        TrieNodeBase node = _root;

        fixed(Char *pin_s = s_in)
        {
            Char *p     = pin_s;
            Char *p_end = p + s_in.Length;

            while (p < p_end)
            {
                if ((node = node[*p]) == null)
                {
                    return(default(TValue));
                }
                p++;
            }
            return(node.Value);
        }
    }
Exemple #15
0
    /// <summary>
    /// note: only returns nodes with non-null values
    /// </summary>
    public void EnumerateLeafPaths(Action <String, IEnumerable <TrieNodeBase> > callback)
    {
        Stack <TrieNodeBase> stk = new Stack <TrieNodeBase>();

        Char[] rgch = new Char[100];

        Action <TrieNodeBase> fn = null;

        fn = (TrieNodeBase cur) =>
        {
            if (stk.Count >= rgch.Length)
            {
                Char[] tmp = new Char[rgch.Length * 2];
                Buffer.BlockCopy(rgch, 0, tmp, 0, rgch.Length * sizeof(Char));
                rgch = tmp;
            }
            foreach (var kvp in cur.CharNodePairs())
            {
                rgch[stk.Count] = kvp.Key;
                TrieNodeBase n = kvp.Value;
                stk.Push(n);
                if (n.Nodes != null)
                {
                    fn(n);
                }
                else
                {
                    if (n.Value == null)                                // leaf nodes should always have a value
                    {
                        throw new Exception();
                    }
                    callback(new String(rgch, 0, stk.Count), stk);
                }
                stk.Pop();
            }
        };

        fn(_root);
    }
Exemple #16
0
    /// <summary>
    /// note: only returns nodes with non-null values
    /// </summary>
    public void DepthFirstTraverse(Action <String, TrieNodeBase> callback)
    {
        Char[] rgch  = new Char[100];
        int    depth = 0;

        Action <TrieNodeBase> fn = null;

        fn = (TrieNodeBase cur) =>
        {
            if (depth >= rgch.Length)
            {
                Char[] tmp = new Char[rgch.Length * 2];
                Buffer.BlockCopy(rgch, 0, tmp, 0, rgch.Length * sizeof(Char));
                rgch = tmp;
            }
            foreach (var kvp in cur.CharNodePairs())
            {
                rgch[depth] = kvp.Key;
                TrieNodeBase n = kvp.Value;
                if (n.Nodes != null)
                {
                    depth++;
                    fn(n);
                    depth--;
                }
                else if (n.Value == null)                               // leaf nodes should always have a value
                {
                    throw new Exception();
                }

                if (n.Value != null)
                {
                    callback(new String(rgch, 0, depth + 1), n);
                }
            }
        };

        fn(_root);
    }
Exemple #17
0
    public IEnumerable <TValue> AllSubstringValues(String s)
    {
        int i_cur = 0;

        while (i_cur < s.Length)
        {
            TrieNodeBase node = _root;
            int          i    = i_cur;
            while (i < s.Length)
            {
                node = node[s[i]];
                if (node == null)
                {
                    break;
                }
                if (node.Value != null)
                {
                    yield return(node.Value);
                }
                i++;
            }
            i_cur++;
        }
    }
Exemple #18
0
 public abstract void ReplaceChild(Char c, TrieNodeBase n);
Exemple #19
0
 public override void ReplaceChild(Char c, TrieNodeBase n)
 {
     d[c] = n;
 }