예제 #1
0
        /// <summary>
        /// 直列化した表を作成
        /// </summary>
        /// <returns></returns>
        public StringDictionary <T> Build()
        {
            var trie          = new Trie();
            var codes_builder = new DoubleArrayCodesBuilder();

            foreach (var key_value in m_key_value)
            {
                trie.Add(key_value.Key);
                codes_builder.Add(key_value.Key);
            }


            var base_array = new BaseCheckArray()
            {
                0, 1
            };
            var check_array = new BaseCheckArray()
            {
                0, 1
            };
            var codes            = codes_builder.Build();
            var state_dictionary = new Dictionary <Guid, int>();

            // 現在のステート
            int?current_state = null;

            foreach (var node in trie.GetEnumerator())
            {
                /// 一番最初なら初期値設定
                if (!current_state.HasValue)
                {
                    state_dictionary[node.Guid] = 1;
                }
                current_state = state_dictionary[node.Guid];



                /// baseの設定
                /// 終端なのでvalueのindexを反転して設定
                if ((node.Value == '\x0000') && node.Children.Count == 0)
                {
                    setToList(ref base_array, current_state.Value, -node.Index.Value);
                    continue;
                }



                /// 設定するbaseの検索 設定
                int  current_base = getFromList(base_array, current_state.Value);
                bool is_colided   = false;
                do
                {
                    is_colided = false;
                    foreach (var child in node.Children)
                    {
                        var code = codes[child.Value];
                        Debug.Assert(0 < code);
                        int next = current_base + code;
                        if (getFromList(check_array, next) != 0)
                        {
                            is_colided    = true;
                            current_base += 1;
                            break;
                        }
                    }
                } while (is_colided);
                setToList(ref base_array, current_state.Value, current_base);

                /// 子の設定
                foreach (var child in node.Children)
                {
                    var code = codes[child.Value];
                    Debug.Assert(0 < code);
                    int next = current_base + code;

                    state_dictionary[child.Guid] = next;
                    if (getFromList(check_array, next) == 0)
                    {
                        // 未使用
                        setToList(ref check_array, next, current_state.Value);
                    }
                    else
                    {
                        // 衝突時処理
                        resolveCollision(current_state.Value, node, state_dictionary, codes, base_array, check_array);
                    }
                }
            }


            return(new StringDictionary <T>(
                       new DoubleArray(base_array, check_array, codes),
                       m_key_value.Values));;
        }
예제 #2
0
        /// <summary>
        /// double arrayの衝突の解決
        /// </summary>
        /// <param name="state"></param>
        /// <param name="node"></param>
        /// <param name="state_dictionary"></param>
        /// <param name="codes"></param>
        /// <param name="base_array"></param>
        /// <param name="check_array"></param>
        private void resolveCollision(int state, Trie.TrieNode node,
                                      Dictionary <Guid, int> state_dictionary, DoubleArrayCodes codes,
                                      BaseCheckArray base_array, BaseCheckArray check_array)
        {
            int old_base = base_array[state];
            int new_base = old_base;

            // 衝突しない新しいbaseを検索
            bool is_colided = false;

            do
            {
                if (is_colided)
                {
                    ++new_base;
                }
                is_colided = false;
                foreach (var child in node.Children)
                {
                    int code = codes[child.Value];
                    Debug.Assert(0 < code);
                    int candidate = new_base + code;
                    if (check_array[candidate] != 0)
                    {
                        is_colided = true; break;
                    }
                }
            } while (is_colided);



            // 新しいbaseに従って子の衝突の解消
            foreach (var child in node.Children)
            {
                var code = codes[child.Value];
                Debug.Assert(0 < code);
                int next = new_base + code;

                /// 新しい遷移先にcheckを設定
                state_dictionary[child.Guid] = next;
                setToList(ref check_array, next, state);

                int move_base = getFromList(base_array, old_base + code);
                setToList(ref base_array, next, move_base);

                if (move_base != 0)
                {
                    // 古い遷移先
                    int old_transit_pos = old_base + code;

                    // 古い遷移先から次に飛んだところ
                    for (int i = old_transit_pos; i < check_array.Count; ++i)
                    {
                        if (check_array[i] == old_transit_pos)
                        {
                            setToList(ref check_array, i, next);
                        }
                    }

                    /// 古い遷移先をリセット
                    setToList(ref base_array, old_transit_pos, 0);
                    setToList(ref check_array, old_transit_pos, 0);
                }
            }


            setToList(ref base_array, state, new_base);
        }