乱伦中文-乱伦种子-乱伦种子下载-乱伦资源站-乱码欧美孕交-乱片免费-乱洤视频-乱人伦30p

服務熱線02152235399
當前位置:博客 > 生物信息

An Implementation of Double-Array Trie 雙數組Trie的一種實現

時間:2018-10-22    |    閱讀量:5828


原文http://linux.thai.net/~thep/datrie/datrie.html

引文:http://quweiprotoss.blog.163.com/blog/static/4088288320091120112155178/

Contents

1. What is Trie?

2. What Does It Take to Implement a Trie?

3. Tripple-Array Trie

4. Double-Array Trie

5. Suffix Compression

6. Key Insertion

7. Key Deletion

8. Double-Array Pool Allocation

9. An Implementation

10. Download

11. References

What is Trie?

Trie is a kind of digital search tree. (See [Knuth1972] for the detail of digital search tree.)[Fredkin1960] introduced the trie terminology, which is abbreviated from "Retrieval".

Trie是一種數字搜索樹,[Fredkin]引入了trie這個術語,它是Retrieval的縮寫。

Trie is an efficient indexing method. It is indeed also a kind of deterministic finite automaton (DFA) (See[Cohen1990], for example, for the definition of DFA). Within the tree structure, each node corresponds to a DFA state, each (directed) labeled edge from a parent node to a child node corresponds to a DFA transition. The traversal starts at the root node. Then, from head to tail, one by one character in the key string is taken to determine the next state to go. The edge labeled with the same character is chosen to walk. Notice that each step of such walking consumes one character from the key and descends one step down the tree. If the key is exhausted and a leaf node is reached, then we arrive at the exit for that key. If we get stuck at some node, either because there is no branch labeled with the current character we have or because the key is exhausted at an internal node, then it simply implies that the key is not recognized by the trie.

Trie是一種高效的索引方法,它實際上是一種確定有限自動機(DFA),在樹的結構中,每一個結點對應一個DFA狀態,每一個從父結點指向子結點(有向)標記的邊對應一個DFA轉換。遍歷從根結點開始,然后從head到tail,由關鍵詞(本想譯成鍵字符串,感太別扭)的每個字符來決定下一個狀態,標記有相同字符的邊被選中做移動。注意每次這種移動會從關鍵詞中消耗一個字符并走向樹的下一層,如果這個關鍵字符串空了,并且走到了葉子結點,那么我們達到了這個關鍵詞的出口。如果我們被困在了一點結點,比如因為沒有分枝被標記為當前我們有的字符,或是因為關鍵字符串在中間結點就空了,這表示關鍵字符串沒有被trie認出來。

Notice that the time needed to traverse from the root to the leaf is not dependent on the size of the database, but is proportional to the length of the key. Therefore, it is usually much faster than B-tree or any comparison-based indexing method in general cases. Its time complexity is comparable with hashing techniques.

注意從根遍歷到葉子的時間不依賴于數據量的大小,而與關鍵詞的長度成比例。也就是它通常比B-tree要快的多,或是比任何基于比較的索引方法在一般情況下都快的多。它的時間復雜度可以與hashing技術相比。

In addition to the efficiency, trie also provides flexibility in searching for the closest path in case that the key is misspelled. For example, by skipping a certain character in the key while walking, we can fix the insertion kind of typo. By walking toward all the immediate children of one node without consuming a character from the key, we can fix the deletion typo, or even substitution typo if we just drop the key character that has no branch to go and descend to all the immediate children of the current node.

除了效率,trie可以當關鍵詞被拼錯了時,提供靈活的搜索。比如在遍歷時忽略一個特定的字符,我們可以修正多輸入的這種輸入錯誤。直接遍歷所有直接的子結點而不消耗一個字符,這樣我可以修正少輸的輸入錯誤,或者甚至替換輸入的錯誤,如果我們沒有分支可以向下移動,就向當前結點的所有子結點直接向下移動。

What Does It Take to Implement a Trie?

In general, a DFA is represented with a transition table, in which the rows correspond to the states, and the columns correspond to the transition labels. The data kept in each cell is then the next state to go for a given state when the input is equal to the label.

通常,一個DFA是用一個transition table表示,它的行對應狀態s,它的列對應轉換標簽s。每一個單元中的數據當輸入與標記相同時,給定一個狀態后要到達的狀態。

This is an efficient method for the traversal, because every transition can be calculated by two-dimensional array indexing. However, in term of space usage, this is rather extravagant, because, in the case of trie, most nodes have only a few branches, leaving the majority of the table cells blanks.

這是一個的遍歷高效方法,因為每次轉換可以通過計算二維的數組索引得到。但是,從空間使用的角度看,這是相當浪費的,因為,在trie這種情況中,大多數結點只有少量的分枝,表中大多數單元是空白的。

Meanwhile, a more compact scheme is to use a linked list to store the transitions out of each state. But this results in slower access, due to the linear search.

同時,一個更緊湊的方式是用鏈表保存每個狀態的轉移,但這種方式會比較慢,因為要進行線性搜索

Hence, table compression techniques which still allows fast access have been devised to solve the problem.

所以,建議使用可以快速訪問的表壓縮技術。

1. [Johnson1975] (Also explained in [Aho+1985] pp. 144-146) represented DFA with four arrays, which can be simplified to three in case of trie. The transition table rows are allocated in overlapping manner, allowing the free cells to be used by other rows.

2. [Aoe1989] proposed an improvement from the three-array structure by reducing the arrays to two.

Tripple-Array Trie

As explained in [Aho+1985] pp. 144-146, a DFA compression could be done using four linear arrays, namely default, base, next, and check. However, in a case simpler than the lexical analyzer, such as the mere trie for information retrieval, the default array could be omitted. Thus, a trie can be implemented using three arrays according to this scheme.

在[Aho+1985]中解釋到,一個DFA壓縮可以用四個數據來完成,分別是default, base, next, check。但是與語法分析不同,比如用于信息檢索的trie,default可以被忽略。所以,一個trie可以用三個數組來實現。

Structure

The tripple-array structure is composed of:

1. base. Each element in base corresponds to a node of the trie. For a trie nodes, base[s] is the starting index within the next and check pool (to be explained later) for the row of the node s in the transition table.

2. next. This array, in coordination with check, provides a pool for the allocation of the sparse vectors for the rows in the trie transition table. The vector data, that is, the vector of transitions from every node, would be stored in this array.

3. check. This array works in parallel to next. It marks the owner of every cell in next. This allows the cells next to one another to be allocated to different trie nodes. That means the sparse vectors of transitions from more than one node are allowed to be overlapped.

三數組結構包括:

1.  base.在base中的每個元素對應trie中的一個結點,對于一個trie結點s,base[s]是next和check pool的起始索引,它們是在轉移表中結點s的行。

2.  next. 這個數組,與check配合,提供一個pool來分配trie轉移表中稀疏向量。這個向量數據是從每一個結點的轉移向量,會被保存在這個數組中。

3.  check. 這個數組與next平行地工作。它標記在next單元的owner。它允許單元s轉移到別一個單元可以分配到不同的trie結點s。這意味著轉移s 的稀疏向量s可以從不同的結點轉移到。

Definition 1. For a transition from state s to t which takes character c as the input, the condition maintained in the tripple-array trie is:

check[base[s] + c] = s

next[base[s] + c] = t

定義 1. 對于從狀態s將c做為輸入,轉移到t,保存在三數組中trie條件是:

check[base[s] + c] = s

next[base[s] + c] = t

Walking

According to definition 1, the walking algorithm for a given state s and the input character c is:

根據定義1,對于一個給定狀態s和一個輸入字符c,移動算法如下:

t := base[s] + c;

if check[t] = s then

next state := next[t]

else

fail

endif

Construction

To insert a transition that takes character c to traverse from a state s to another state t, the cellnext[base[s] + c]] must be managed to be available. If it is already vacant, we are lucky. Otherwise, either the entire transition vector for the current owner of the cell or that of the state s itself must be relocated. The estimated cost for each case could determine which one to move. After finding the free slots to place the vector, the transition vector must be recalculated as follows. Assuming the new place begins at b, the procedure for the relocation is:

插入一個從狀態s到另一個狀態t的轉移,單元next[base[s]+c]必須是空閑的。如果它就是空的,那么我們很幸運。不然,或是將當前 owner的整個轉移向量重新分配,或是狀態s自己要重新分配。這兩種情況的估計代價會決定采用哪用方式。在找到空閑的位置來放這個向量,轉移向量必須重新如下計算,假設新的位置開始于b,重新分配的過程如下:

Procedure Relocate(s : state; b : base_index)

{ Move base for state s to a new place beginning at b }

begin

foreach input character c for the state s

{ i.e. foreach c such that check[base[s] + c]] = s }

begin

check[b + c] := s;     { mark owner }

next[b + c] := next[base[s] + c];     { copy data }

check[base[s] + c] := none { free the cell }

end;

base[s] := b

end

Double-Array Trie

The tripple-array structure for implementing trie appears to be well defined, but is still not practical to keep in a single file. The next/check pool may be able to keep in a single array of integer couples, but thebase array does not grow in parallel to the pool, and is therefore usually split.

三數組結構來實現trie看真似為是一個很好的方式,但是將它保存到一個單一文件還是不現實的,next/check pool也許可以保存在整型對的一個單個數組,但是base數組不與pool平行地增長,所以通常分離。

To solve this problem, [Aoe1989] reduced the structure into two parallel arrays. In the double-array structure, the base and next are merged, resulting in only two parallel arrays, namely, base and check.

解決這個問題,[Aoe1989]減少這個結構到二個平行的數組,在這個雙數組結構中,將base和next合并,它只使用兩個平行的數組為,base和check。

Structure

Instead of indirectly referencing through state numbers as in tripple-array trie, nodes in double-array trie are linked directly within the base/check pool.

不同于三數組trie中通過狀態號間接引用,在雙數組trie是直接在base / check pool中鏈接。

Definition 2. For a transition from state s to t which takes character c as the input, the condition maintained in the double-array trie is:

check[base[s] + c] = s

base[s] + c = t

定義2. 對于一個接收字符c從狀態s移動到t的轉移,在雙數組中保存的條件是:

check[base[s] + c] = s

base[s] + c = t

Walking

According to definition 2, the walking algorithm for a given state s and the input character c is:

根據定義2,對于從狀態s接收輸入c的移動算法如下:

t := base[s] + c;

if check[t] = s then

next state := t

else

fail

endif

Construction

The construction of double-array trie is in principle the same as that of tripple-array trie. The difference is the base relocation:

構造雙數組trie在原理上是與三數組trie相同的,不同點在于base的重新定位。

Procedure Relocate(s : state; b : base_index)

{ Move base for state s to a new place beginning at b }

begin

foreach input character c for the state s

{ i.e. foreach c such that check[base[s] + c]] = s }

begin

check[b + c] := s;     { mark owner }

base[b + c] := base[base[s] + c];     { copy data }

{ the node base[s] + c is to be moved to b + c;

Hence, for any i for which check[i] = base[s] + c, update check[i] to b+ c }

foreach input character d for the node base[s] + c

begin

check[base[base[s] + c] + d] := b + c

end;

check[base[s] + c] := none { free the cell }

end;

base[s] := b

end

Suffix Compression

[Aoe1989] also suggested a storage compression strategy, by splitting non-branching suffixes into single string storages, called tail, so that the rest non-branching steps are reduced into mere string comparison.

[Aoe1989]也建議了一種壓縮策略,通過拆分non-branching后綴到單一字符串保存,稱為tail,這樣剩余的non-branching步驟就減為字符串壓縮了。

With the two separate data structures, double-array branches and suffix-spool tail, key insertion and deletion algorithms must be modified accordingly.

使用兩種不同的數據結構,雙數組分枝和suffix-spool tail,關鍵詞插入和刪除算法也必須相應的修改。

Key Insertion

To insert a new key, the branching position can be found by traversing the trie with the key one by one character until it gets stuck. The state where there is no branch to go is the very place to insert a new edge, labeled by the failing character. However, with the branch-tail structure, the insertion point can be either in the branch or in the tail.

插入一個新的關鍵詞,分枝位置可以通過關鍵詞中的字符遍歷trie,直到它困住。這種狀態就是沒有分枝可以走,要插入一個新的邊的位置,這個邊標記為那個失敗的字符。然而,用branch-tail結構,插入點可以在branch或是tail。

1. When the branching point is in the double-array structure

Suppose that the new key is a string a1a2...ah-1ahah+1...an, where a1a2...ah-1 traverses the trie from the root to a node sr in the double-array structure, and there is no edge labeled ah that goes out of sr. The algorithm called A_INSERT in [Aoe1989] does as follows:

假設一個新的key是一個字符串a1a2...ah-1ahah+1...an,其中a1a2...ah-1從trie的根遍歷到結點sr,并且沒有邊標記為ah可以走出sr。這個算法稱為A_INSERT在[Aoe1989]中如下操作:

From sr, insert edge labeled ah to new node st;

Let st be a separate node poining to a string ah+1...an in tail pool.

2. When the branching point is in the tail pool

Since the path through a tail string has no branch, and therefore corresponds to exactly one key, suppose that the key corresponding to the tail is

a1a2...ah-1ah...ah+k-1b1...bm,

where a1a2...ah-1 is in double-array structure, and ah...ah+k-1b1...bm is in tail. Suppose that the substring a1a2...ah-1 traverses the trie from the root to a node sr.

And suppose that the new key is in the form

a1a2...ah-1ah...ah+k-1ah+k...an,

where ah+k <> b1. The algorithm called B_INSERT in [Aoe1989] does as follows:

當路徑經過tail字符串沒有branch,所以對應一個關鍵詞,假設在tail這個關鍵詞對應的是:

a1a2...ah-1ah...ah+k-1b1...bm,

其中a1a2...ah-1在雙數組結構中,而ah...ah+k-1b1...bm在tail。假設子串a1a2...ah-1遍歷trie從根到sr。

并假設這個新的關鍵詞是如下形式:

a1a2...ah-1ah...ah+k-1ah+k...an,

其中ah+k <> b1。這個算法在[Aoe1989]中被稱為B_INSERT如下操作:

From sr, insert straight path with ah...ah+k-1, ending at a new node st;

From st, insert edge labeled b1 to new node su;

Let su be separate node pointing to a string b2...bm in tail pool;

From st, insert edge labeled ah+k to new node sv;

Let sv be separate node pointing to a string ah+k+1...an in tail pool.

Key Deletion

To delete a key from the trie, all we need to do is delete the tail block occupied by the key, and all double-array nodes belonging exclusively to the key, without touching any node belonging to other keys.

從trie中刪除一個關鍵詞,我們僅需要的是刪除被這個關鍵詞占有的tail塊,和所有只屬于這個關鍵詞的雙數組結點,不改變其它關鍵詞的結點。

Consider a trie which accepts a language K = {pool#, prepare#, preview#, prize#, produce#, producer#, progress#} :

考慮一個trie,它接收語言K = {pool#, prepare#, preview#, prize#, produce#, producer#, progress#} :

The key "pool#" can be deleted by removing the tail string "ol#" from the tail pool, and node 3 from the double-array structure. This is the simplest case.

關鍵詞"pool#"可以通過從tail pool移除tail字符串"ol#",即雙數組結構中的結點3,這是最簡單的情況。

To remove the key "produce#", it is sufficient to delete node 14 from the double-array structure. But the resulting trie will not obay the convention that every node in the double-array structure, except the separate nodes which point to tail blocks, must belong to more than one key. The path from node 10 on will belong solely to the key "producer#".

移除關鍵詞"produce#",從雙數組結構中刪除結點14就可以了,但是產生的trie不再遵循trie的定義,即除指向tail塊的分離的結點外,必須屬于多個關鍵詞。從結點10的路徑僅屬于關鍵詞"producer#"。

But there is no harm violating this rule. The only drawback is the uncompactnesss of the trie. Traversal, insertion and deletion algoritms are intact. Therefore, this should be relaxed, for the sake of simplicity and efficiency of the deletion algorithm. Otherwise, there must be extra steps to examine other keys in the same subtree ("producer#" for the deletion of "produce#") if any node needs to be moved from the double-array structure to tail pool.

但是違反這個規則沒有什么壞處。唯一的缺點是trie不緊湊。遍歷,插入,刪除算法都是不改變的。所以,出于刪除算法簡單和高效,這是可以放寬的。不然,必須有額外的步驟來檢查其它在相同子樹的關鍵詞,看是否其它結點需要從雙數組結構刪除到 tail pool。

Suppose further that having removed "produce#" as such (by removing only node 14), we also need to remove "producer#" from the trie. What we have to do is remove string "#" from tail, and remove nodes 15, 13, 12, 11, 10 (which now belong solely to the key "producer#") from the double-array structure.

進一步假設刪除的除了"produce#"(只刪除結點14),我們還需要從trie中刪除"producer#"。我們需要做的是從tail中刪除"#",并刪除15, 13, 12, 11, 10(它們僅屬于關鍵詞"producer#")。

We can thus summarize the algorithm to delete a key k = a1a2...ah-1ah...an, where a1a2...ah-1 is in double-array structure, and ah...an is in tail pool, as follows :

我們可以總結這個算法,其中刪除了一個關鍵詞k = a1a2...ah-1ah...an,其中a1a2...ah-1是在雙數組結構中,且ah...an在tail pool中, 如下:

Let sr := the node reached by a1a2...ah-1;

Delete ah...an from tail;

s := sr;

repeat

p := parent of s;

Delete node s from double-array structure;

s := p

until s = root or outdegree(s) > 0.

Where outdegree(s) is the number of children nodes of s.

其中outdegree(s)是s的子結點數。

Double-Array Pool Allocation

When inserting a new branch for a node, it is possible that the array element for the new branch has already been allocated to another node. In that case, relocation is needed. The efficiency-critical part then turns out to be the search for a new place. A brute force algorithm iterates along the check array to find an empty cell to place the first branch, and then assure that there are empty cells for all other branches as well. The time used is therefore proportional to the size of the double-array pool and the size of the alphabet.

當對一個結點插入一個新的分枝,有可能數組中為新的分枝的位置已經分配給了其它結點,在這種情況下,需要重新定位,影響效率的部分就是尋找一個新的位置,一種brute force(蠻力)算法迭代check數組找出一個空的單元來放置第一個分枝,然后假設還有空的單元來放其它的分枝。所以時間復雜性與雙數組的大小和字母集的大小成正比。

Suppose that there are n nodes in the trie, and the alphabet is of size m. The size of the double-array structure would be n + cm, where c is a coefficient which is dependent on the characteristic of the trie. And the time complexity of the brute force algorithm would be O(nm + cm2).

假設在trie中有n個結點,字母集的大小為m。雙數組結構的大小為n+cm,其中c是一個依賴trie字符形式的一個系數。Brute force算法的時間復雜性是O(nm + cm2)。

[Aoe1989] proposed a free-space list in the double-array structure to make the time complexity independent of the size of the trie, but dependent on the number of the free cells only. The check array for the free cells are redefined to keep a pointer to the next free cell (called G-link) :

[Aoe1989]提出了在雙數組結構中一個free-space list使時間復雜性與trie的大小無關,但僅與空閑單元的方法。Check數組的空閑單元被重定義為保存一下指向下一個空閑單元的指針(稱為G-link):

Definition 3. Let r1, r2, ... , rcm be the free cells in the double-array structure, ordered by position. G-link is defined as follows :

check[0] = -r1

check[ri] = -ri+1 ; 1 <= i <= cm-1

check[rcm] = -1

定義3. 令r1, r2, ... , rcm為雙數組結構中的空閑單元,以位置排序。G-link定義如下:

check[0] = -r1

check[ri] = -ri+1 ; 1 <= i <= cm-1

check[rcm] = -1

By this definition, negative check means unoccupied in the same sense as that for "none" check in the ordinary algorithm. This encoding scheme forms a singly-linked list of free cells. When searching for an empty cell, only cm free cells are visited, instead of all n + cm cells as in the brute force algorithm.

根據這個定義,負check意味著空閑與在普通算法中的"none" check是同一個意思,這種編碼方式形成了一個空閑單無單一鏈接的鏈表。當搜索一個空閑單元,僅cm空閑單元被訪問,而不是在brute force算法中的所有n+cm。

This, however, can still be improved. Notice that for those cells with negative check, the correspondingbase's are not given any definition. Therefore, in our implementation, Aoe's G-link is modified to be doubly-linked list by letting base of every free cell points to a previous free cell. This can speed up the insertion and deletion processes. And, for convenience in referencing the list head and tail, we let the list be circular. The zeroth node is dedicated to be the entry point of the list. And the root node of the trie will begin with cell number one.

這仍然是可以提高的,注意那些是負check的單元,對應的base單元沒有任何給定的定義,所以,在我們的實現中,Aoe’s G-link被修改為雙鏈接的列表,使base中的每一個空閑單元指到前一個空閑單元。這可以提高插入和刪除的速度。并且為了方便引用列表的頭和尾,我們使用了循環鏈表,第0個結點被指定為列表的入口。并且trie的根結點開始于第1個單元。

Definition 4. Let r1, r2, ... , rcm be the free cells in the double-array structure, ordered by position. G-link is defined as follows :

check[0] = -r1

check[ri] = -ri+1 ; 1 <= i <= cm-1

check[rcm] = 0

base[0] = -rcm

base[r1] = 0

base[ri+1] = -ri ; 1 <= i <= cm-1

定義4. 令r1, r2, ... , rcm為雙數組結構中的空閑單元,以位置排序,G-link的定義如下:

check[0] = -r1

check[ri] = -ri+1 ; 1 <= i <= cm-1

check[rcm] = 0

base[0] = -rcm

base[r1] = 0

base[ri+1] = -ri ; 1 <= i <= cm-1

Then, the searching for the slots for a node with input symbol set P = {c1, c2, ..., cp} needs to iterate only the cells with negative check :

那么,為輸入符號集P = {c1, c2, ..., cp}尋找一個結點的單元,只需要在有負check的單元中迭代。

{find least free cell s such that s > c1}

s := -check[0];

while s <> 0 and s <= c1 do

s := -check[s]

end;

if s = 0 then return FAIL;  {or reserve some additional space}

{continue searching for the row, given that s matches c1}

while s <> 0 do

i := 2;

while i <= p and check[s + ci - c1] < 0 do

i := i + 1

end;

if i = p + 1 then return s - c1;  {all cells required are free, so return it}

s := -check[-s]

end;

return FAIL;  {or reserve some additional space}

The time complexity for free slot searching is reduced to O(cm2). The relocation stage takes O(m2). The total time complexity is therefore O(cm2 + m2) = O(cm2).

搜索slot的時間復雜度下降到O(cm2)。重定位步驟占O(m2)。所以全部的時間復雜度是O(cm2 + m2) = O(cm2)。

It is useful to keep the free list ordered by position, so that the access through the array becomes more sequential. This would be beneficial when the trie is stored in a disk file or virtual memory, because the disk caching or page swapping would be used more efficiently. So, the free cell reusing should maintain this strategy :

將free list以位置排序是有好處的,這樣訪問位置可以是順序訪問,當trie保存在磁盤文件或是虛擬內存中,這會是有好處的,因為磁盤緩存和交換頁的使用會更有效。所以,空閑單元重用應保持這個策略。

t := -check[0];

while check[t] <> 0 and t < s do

t := -check[t]

end;

{t now points to the cell after s' place}

check[s] := -t;

check[-base[t]] := -s;

base[s] := base[t];

base[t] := -s;

Time complexity of freeing a cell is thus O(cm).

釋放一個單元的時間復雜度是O(cm)。

An Implementation

In my implementation, I exploit the concept of virtual memory to manage large and permenent trie. A base class called VirtualMem divides the data file into pages, and swaps them in as needed. Memory economy and disk caching is thus achieved. Different memory accessing methods are provided so that the page swapping mechanism is hidden from the class users. Meanwhile, byte order is internally managed on-the-fly inside the methods to achieve data portability.

Double-array structure and tail pool are then built upon the VirtualMem base class. Trie class is then created to contain the two data structures, with basic interfaces for trie manipulation.

Download

Update: The double-array trie implementation has been simplified and rewritten from scratch in C, and is now named libdatrie. It is now available under the terms of GNU Lesser General Public License (LGPL):

· libdatrie-0.2.2 (29 April 2009)

· libdatrie-0.2.1 (5 April 2009)

· libdatrie-0.2.0 (24 March 2009)

· libdatrie-0.1.3 (28 January 2008)

· libdatrie-0.1.2 (25 August 2007)

· libdatrie-0.1.1 (12 October 2006)

· libdatrie-0.1.0 (18 September 2006)

SVN: svn co http://linux.thai.net/svn/software/datrie

The old C++ source code below is under the terms of GNU Lesser General Public License (LGPL):

· midatrie-0.3.3 (2 October 2001)

· midatrie-0.3.3 (16 July 2001)

· midatrie-0.3.2 (21 May 2001)

· midatrie-0.3.1 (8 May 2001)

· midatrie-0.3.0 (23 Mar 2001)

References

1. [Knuth1972] Knuth, D. E. The Art of Computer Programming Vol. 3, Sorting and Searching. Addison-Wesley. 1972.

2. [Fredkin1960] Fredkin, E. Trie Memory. Communication of the ACM. Vol. 3:9 (Sep 1960). pp. 490-499.

3. [Cohen1990] Cohen, D. Introduction to Theory of Computing. John Wiley & Sons. 1990.

4. [Johnson1975] Johnson, S. C. YACC-Yet another compiler-compiler. Bell Lab. NJ. Computing Science Technical Report 32. pp.1-34. 1975.

5. [Aho+1985] Aho, A. V., Sethi, R., Ullman, J. D. Compilers : Principles, Techniques, and Tools. Addison-Wesley. 1985.

6. [Aoe1989] Aoe, J. An Efficient Digital Search Algorithm by Using a Double-Array Structure. IEEE Transactions on Software Engineering. Vol. 15, 9 (Sep 1989). pp. 1066-1077.

7. [Virach+1993] Virach Sornlertlamvanich, Apichit Pittayaratsophon, Kriangchai Chansaenwilai. Thai Dictionary Data Base Manipulation using Multi-indexed Double Array Trie. 5th Annual Conference. National Electronics and Computer Technology Center. Bangkok. 1993. pp 197-206. (in Thai)






主站蜘蛛池模板: 在线三级视频网址 | 日本高清大片 | 国产视频99 | 丁香五月花伊人网 | 国产99在| 国产在线观看区 | 日韩A∨视频 | 久久亚洲影视无码 | 国产91免费视频 | 久草福利视频网 | 岛国无码一卡二卡 | 动漫自慰18 | 麻豆视频黄色 | 在线看黄色96 | 黑料一区在线 | 黄片五码 | 国产天美三级网站 | 成人动漫网站观看 | 国产成人短视频 | 日韩美女高清mv | 欧美入口| 成人论坛视频在线 | 免费黄页网 | 自拍偷探花 | A片播放地址 | 激情播播五月婷婷 | 黄色片导航 | 日韩中文字幕观看 | 殴美性之站 | 成人免费精品视频 | 国产情侣亚洲 | 欧美国产日韩亚洲 | 国产啪亚洲国 | 亚洲色图婷婷五月 | 国产精品豆花视频 | 国产高清激情 | 亚洲视频一区网站 | 亚州欧美另类色图 | 日本乱伦电影网站 | 羞羞视频免费看 | 蜜臀麻豆 | 白丝一区二区三区 | 91自拍精品 | 91看片在线观看 | 午夜主播福利视频 | 岛国大片免费观看 | 无码免费精品 | 国产在线播放视频 | 午夜V影院一起草 | 亚洲欧美国产 | 孕妇国产一区 | 校园春色欧美综合 | 激情AV无码 | 国产伦理自拍 | 国产丝袜一区0 | 国产精品性| 四虎私人影视 | 青青草国语版 | 成人精品无| 日本国产在线视频 | 在线草久| 免费毛片网站 | BT在线观看 | 国产高清无码二区 | 久久精品女性视频 | 日韩少妇精品视频 | 日韩成人免费网站 | 91茄子短视频 | 91香蕉视频软件 | 国产美女视频网站 | 调教丝袜人妻视频 | 高清无码在线 | 国产精品果冻传媒 | 欧美干逼视频 | 操操操碰| 强奸少妇影院 | 年亚洲欧美在线v | 成人欧美色图电影 | 操片免费看 | 你懂的丁香 | 午夜主播福利视频 | 91插| 欧美乱伦图片 | 激情四月丁香婷婷 | 日本精品视频 | 91猫先生在线 | 91怎么下载 | 超碰aa在线91 | 91欧美人妖 | 日本一级簧片 | 欧美一二三性交 | 欧美精品二区 | 伦理午夜 | 免费观看片子软件 | 国产精品性爱 | 成人精品二区 | 亚洲欧美久久精品 | 午夜视频福利精品 | 国产国产精品 | 欧美a级性片 | 日本www视频 | 91福利社区下载 | 无码草逼| 国产在线吃瓜 | 香港伦理片电影 | 午夜美女福利视频 | 国产精品无码电影 | 福利在线观看视频 | 日韩午夜性影院 | 好看的簧色网址 | 黄色无码岛国 | 欧美性爱网第一页 | 日本天堂在线播放 | 午夜宅男影院 | 91草莓在线 | 欧美精品xxxx | 91成人免费视频 | 91蜜臀网| 欧美4级片| 91高清免费视频 | 超碰在线91太久 | 国产福利精品电影 | 男女午夜亚洲 | 免费91香蕉视频 | 成人高清免费 | 国产在线看视频 | 亚州欧美另类色图 | 91豆花成人网站 | 性爱福利在线 | 深夜福利在线播放 | 波多野吉衣教师 | 东京热自慰影院 | 日美乱伦激情网 | 欧美精品av| 91国产小青蛙 | 91视频免费版黄 | 国产高清中文精品 | 国产精品熟伦视频 | 精品的电影网站 | 欧美乱理片| 91高清国内自产 | av岛国大片网站 | 91国产网| 免费青青草在线 | 日本三级毛 | 青草草视频 | 五月婷色欲 | 欧美色图另类故事 | 亚洲成年网| 日韩性爱影院 | 青草福利社 | 青青草电影 | 激情福利网 | 美日韩第一页 | 欧美色色爱 | 成人国产精品久久 | 欧美中文字幕 | 欧美日韩大黄片 | 午夜精品电影 | 小香蕉操操网 | 狠狠撸亚洲欧美 | 午夜大片福利 | 国产蜜臀av无码 | 最新HD日本电影 | 三级国产三级在线 | 东京热自慰影院 | 青青草白白色 | 欧美图片区无毒 | 新91视频 | 日韩A∨视频 | 无码一区二区 | 三级网站永久大全 | 免费三级黄色网 | 国产在线视频播放 | 国产大片免费观看 | 黄色毛片入口 | 久草福利资源视频 | 日韩三级网 | 成人小视频网址 | 日韩免费在线看 | 黄色三级视频网 | 亚洲AA在线 | 成网站大片 | 黄色网站高清无码 | 男人午夜AV网 | 国产高清三级 | 中文字幕日本在线 | 一级片免费视频 | 亚洲最大福利视频 | 五月天网站亚洲 | 午夜视频福利免费 | 岛国最大色网站 | 国产高清成年网站 | 影音先锋日韩高清 | 5月丁香综合久 | 欧美人妻激情 | 免费看片福利导航 | 丁香网五月导航 | 日本伦理片网站 | 青青草高清视频 | 在线国产二区 | 熟女二区不卡 | 91精品国产高清 | 国产福利网站 | 欧美插插插网 | 午夜两性按摩影院 | 精品日韩中文字幕 | 国产AⅤ无码 | 91在线导航 | 成年人免费网 | 日本黄色国产精品 | 欧美精品高清 | 一国产精品| 精品欧美在线 | 岛国黄片网址 | 国产精品日韩 | 偷拍午夜视频 | 91黄软件| 日韩丝袜中文字幕 | 日韩美女视频0 | 亚洲色色五月天 | 午夜鲁丝无码视频 | 加勒比色网站 | 成人影视一区二区 | 亚洲欧美电影一区 | 18日本三级全黄 | 91视频网站| 男人天堂午夜网 | 日本不卡电影在线 | 很黄免费网站 | 日韩小网 | 日本色站| 成年人午夜网站 | 超碰夫妻91无码 | 爆乳福利视频网 | 成人免费视频欧洲 | 91福利视频网站 | 欧美在线网址 | 91韩剧tv| 乱伦熟女片 | 欧美韩二区 | 久草视频最新 | 福利网站91| 日本韩国www | 激情文学综合网 | 午夜爆乳福利 | 深爱色情网 | 四虎首页 | 国产人妖在线视频 | 国产探花第二页 | 黄色激情性爱 | 欧美疯狂乱伦 | 国产精品在线观看 | 91一道不卡| 欧美黑人性视频 | 国内精品欧美 | 日韩亚洲第九页 | 一起草福利视频 | 超碰在线成人视屏 | 日韩欧美深夜 | 女同微电影 | 国产欧美日韩亚洲 | 国产日韩免费视频 | 无码无毒网站入口 | 亚洲欧美高清 | 无码av免费| 国产精华国产精品 | 免费黄a片 | 国产啪亚洲国产 | 日日日干干干 | 欧美在线天堂视频 | 超碰福利国产 | 丁香五月尤物网 | 日韩成人激情视频 | 欧美日韩另另类 | 欧美老女人bb | 结衣波多野番号 | 综合网黄| 久草香焦| 无码加勒比 | 福利影院精品 | 男人的天堂黄色片 | 成人大片免费 | 青草视频69| 变态另态另类2 | 国产在线综合网 | 国产夫妻精品自拍 | 伦理日韩电影 | 欧美操穴 | 高清无码网址 | 美国伦理在线 | 午夜小视频福利 | 三级黄片亚洲 | 嫩屄在线观看 | 欧洲毛片后入 | 日日操日日碰 | 国产精品第十二页 | 中文字幕一区二区 | 欧美黄色网址 | 91大神康先生 | 四虎激情 | 欧美视频一区 | 羞羞影院黄 | 日本一级性生活片 | 草逼专区政| 欧美不卡 | 欧洲一区二区三区 | 成人天堂入口网站 | 亚洲国内成人 | 国产不卡1| 人妖rose资料| 波多野结番号 | 成人无码在线播放 | 波多野结 | 日本不卡免费高清 | 91人成亚洲高清 | 日韩另类综合 | 欧美系列一区二区 | 国产精品三级在 | 欧美18禁网站 | 福利精品在线视频 | 岛国精品一区二 | 欧美精品羞羞答答 | 免费日本A∨| 性爱视频蜜桃视频 | 欧美二区网站 | 在线日韩欧 | 日日夜夜狠狠撸 | 国产福利在线观 | 国产精品女主播 | 成在线观看 | 欧美a在线 | 日韩欧美性爱 | 欧洲成人午夜精品 | 岛国视频在线 | 欧洲精品黄片 | 青草视频国 | 日韩少妇精品视频 | 91超碰蜜桃| 精品国产无码爽 | 午夜伦理电影网 | 老湿机福利影院 | 牛牛成人导航 | 男人天堂五月天 | 91小视频app| 乱伦五月天| 无码免费A片 | 福利欧美偷拍尤物 | 男黄片免费 | 国产成人无 | 91自拍视频论坛 | 干干干草草草91 | 成人国产高清 | 亚洲欧美综合国产 | 国产福利小视频 | 成人免费视频观看 | 精品午夜福利网 | 91免费高清视频 | 美女白丝自慰网站 | 欧美情片| 中日韩黄色A级片 | 91毛片免费观看 | 免费三级网网站 | 日韩另类在线视频 | 亚洲精品一卡二卡 | 午夜福利视频91 | 操逼黄色网 | 性福AV | 污午夜福利 | 歐美倫理無碼 | 国产V片| 欧美天天艹影院 | 污污A片| 福利视频网站 | 日韩无码伦理 | 91视频成人下载 | 宅宅网伦理片 | 美女视频黄色网 | 欧美日韩夜夜爽 | 日本韩国欧美一区 | 日韩精品视频网站 | 日韩另类一区 | 欧美黄色高清另类 | 亚洲欧美精品视频 | 日韩免费高清电影 | 亚洲人成免费网站 | 国产精品秀秀视频 | 性爱福利网 | 伦理片潘金莲 | 极品成人 | 国产精品福利一区 | 激五丁香婷婷视频 | 青草论坛 | 丁香五月天视频 | 日韩综合另类 | 福利所导航 | 国产欧美日韩成人 | 高清成人免费视频 | 日本三级免费自拍 | 日本在线观看精品 | 国产视频青青 | 日本高清免费观看 | 欧美浮力第一页 | 91自拍在线 | 午夜福利手机在线 | 深夜免费福利网 | 亚洲丁香五月婷婷 | 日本三级精品 | 伦理中文字幕 | 人人干人人操 | 麻豆av入口 | 高清在线www | 操的啊啊叫91 | AV人摸人人人 | 老湿机69| 少妇导航 | 韩日色色 | 羞羞影院午夜 | 久草视频在线资源 | 超清免费在线 | 波多野老师电影 | 精品国偷自产在线 | 狼友的av天堂 | 操操av| 麻豆国产福利精品 | 成人超碰淫湿无码 | 国内自拍青青草 | 萌白酱正在播放 | 尤物福利视频 | 哪里有乱轮A片看 | 加勒比一区 | 国产免费视频网站 | 亚洲性综合 | 欧美性色生活 | 国产精品玉足 | 美女内射毛片3D | 亚洲第九页 | 青青草在线资源 | 国产熟女视频在线 | 中文字幕高清 | 在线看日本三级 | 日韩一区在线看 | 国产在线偷拍自拍 | 国产福利免费 | 麻豆tv在线观看 | 成人动漫在线观看 | 国内日韩欧美 | 欧美精品免费视频 | 伦理电影日韩 | 91网址在线播放 | 欧美高潮潮喷 | 日韩第九十一页 | 狠狠操狠狠撸 | 高清国产剧第1页 | 久久午夜伦理片 | 精品孕妇精品在线 | 亚洲自拍棚社区 | 狠狠撸视频网站 | 伦理片日韩| 深爱网人妻区 | 国产视频538| 日本成年人网站 | 97国产在| 麻豆精品国产91 | 人人干人人操 | 优酸乳成人无码片 | 日韩剧情片视频 | 国产原创一区二区 | 成人毛片高清无码 | 精品国产白浆 | 成人爱草草 | 日韩欧美色网大全 | 日韩高清免费电影 | 日韩中文字幕综合 | 成年人午夜影院 | 宅男视频APP污 | 黄色av网页| 日韩福利社 | 黄色网址在线播放 | 国产美女视频网站 | 日韩激情A片影院 | 无码在线视频播放 | 丁香五月免费看 | 国产精品特级露脸 | 成人欧美视频 | 综合欧美另类 | 第一宅男AV导航 | 亚洲日本韩国电影 | 四虎尤物 | 五月激情播播 | 麻豆国产尤物av | 午夜我人在线视频 | 女同论坛 | 三级片第一页 | 国产二区自拍 | 欧美色图片区 | 国产二区在线观看 | 日日操日日干 | 豆奶视频成人 | 福利影院在线 | 免费美女啪啪视频 | 免费观看高清直播 | 国产在线直播播放 | 欧美成人视频导航 | 亚洲欧美日本韩国 | 国产一区a | 国模一区二区欧美 | 欧美日韩一级视频 | 欧美社区 | 欧美日韩精品电影 | 欧美精品网站 | 免费伦理片电影 | 日韩大片视频 | 久久黄色网 | 91短视频免费 | 国产人妖精品区 | 少妇自慰| 超碰碰天天 | 一区二区无码免费 | 国产国产人免 | 欧美孕妇被操视频 | 欧美二区三区 | 91色色在线网站 | 成人无码精品 | 欧美日韩一区不卡 | 嫩逼草草草 | 日本高清一二 | 内射性爱网址大全 | 亚洲视频资源 | 欧美二区日本二区 | 淫秽插人免费网站 | 深夜福利视频 | 高清国产精品自拍 | 午夜国产小电影 | 麻豆传媒18禁| 三级电影网 | 免费五月丁香视频 | 男女爱爱免费网站 | 伦理片电影网站 | bt电影下载| 免费在线伦理电影 | 欧美网址在线观看 | 成人黄色三级 | 日韩另类在线 | 国产亚洲在线观看 | 第一宅男AV导航 | 成人免费无码视频 | 尤物福利视频 | 综合色精品首页 | 深夜美女福利视频 | 中国一区二区视频 | 美女网站视频黄 | 岛国三级在线看 | 黑料在线国产 | 日韩理论在线播放 | 亚洲图片欧美视频 | 三级黄色图片 | 日韩成人第一页 | 成年人电影网址 | 成人国产wuma | 国产在线视频网站 | 四虎自拍视频 | 国产97视| 日本三级理论片 | 亚洲国产第一网站 | 国产大片a| 欧美乱伦性爱 | 狠狠撸天天日 | 在线观看视频成人 | 日本另类人妖 | 人人澡在线视频 | 欧美日韩一级影院 | 福利久草| 男男黄色影院 | av下载免费观看 | 国产成人黄色视频 | 青春草国产视频 | 91艹逼| 国产日韩成人影片 | 深夜福利网站在线 | 日本乱伦中文字幕 | 亚洲欧美日韩区 | 岛国精品无码 | 精品成人无码视频 | 深爱五月成人 | 成人午夜天堂 | 日韩免费福利 | 日韩中文字幕av | 日本精品成人 | 国产精品91麻豆 | 欧美人交配 | 欧美色色综合 | 午夜成人网 | 福利姬亚洲 | 波多野结快播 | 91不卡在线 | 国产欧美亚洲一区 | 深喉影院导航 | 欧美色图一区二区 | 女人草屄影院黄色 | 欧美精品视频在线 | 亚洲另类都市激情 | 国产绿帽娇妻在线 | 干叉91| 免费三级网站观看 | 日韩伦理在线观看 | 操操操日 | 国产青春片大片 | 欧洲色综合| 亚洲伊人五月花 | 日本在线观看免费 | 五月天亚洲激情 | 丁香五月天成人 | 极品美女一线天 | 欧美在线免费看 | 91免费网址 | 成人午夜免费电影 | 强奸乱伦欧美 | 福利在线aa| 免费三级无毒 | 国产乱子影视频上 | 欧美视频日韩视频 | 欧美18黄色 | 成年人草莓视频 | 97导航 | 能看的毛片网 | 结衣波多野 | 午夜亚洲av日韩 | 国产对白91色拍 | 韩日神马久久 | 在线观看国产网站 | 黄片网站免费观看 | 香蕉干逼 | 日本成人午夜影院 | 亚洲人成在线观 | 免费伦理电影观看 | 伦理片一区 | 91午夜福利国产 | 91直播在线观看 | 国产丝袜熟女 | 欧美伦理另类 | 成人亚洲精品AV | 激播综合网 | 激情五月综合 | 91天天综合| 国产一区二区 | 欧美乱伦xxxx | 欧美精品亚洲 | 欧美另类xxx | 国产偷v在线精品 | 日韩在线二区 | 成人激情视 | 美女视频三级黄 | 成人无码免费观看 | 黄的片网站 | 福利综艺推荐 | 超碰97人妻 | 麻豆传媒亚洲精选 | 欧美精品视频网 | 日韩在线影院 | 日韩免费一级电影 | 香港午夜福利 | 国产无线卡一卡二 | 午夜激情成人 | 丁香五月播| 伦理在线免费观看 | 国产精品成人自拍 | 欧美a级片免费 | 精品免费国产视频 | 国产精品午夜精品 | 成人黄疸图片 | 国产中文免费字幕 | 欧美变态另类影院 | 日韩无码激情深爱 | 亚洲三级伦理片 | 黄色av新网址| 青青草伦理 | 日韩无码MFLI | AV在线三| 国产中文字幕网 | 91婷婷日屄| 国产四级电影 | 欧美狠狠艹 | 福利一区国产 | 香蕉视频操 | 日韩在线欧美首页 | 日日操狠狠 | 欧美韩日无 | 午夜在线试看 | 青草视频在线观 | 午夜亚洲电影 | 日韩无码卡一卡二 | 国产第一页线路1 | 91免費| 国产片一区二 | 日韩喷潮 | 国产香蕉人人 | 国产精品偷伦 | 四虎影院观看 | 成人丝瓜视频 | 91黄色干逼 | 国产成人黄色视频 | 91福利观看| 国产精品自拍三级 | 国产美女抠逼视频 | 精品成人无码 | 在线观看国产高清 | 在线免费看片 | 丁香婷婷五月底 | 夜夜看福利视频 | 夜干日干| 丁香五月婷婷在线 | 91视频人人 | 91人人插 | 日韩资源在线观看 | 91成人在线视频 | 三级黄片毛片 | 久草色香蕉视频 | 国产日本欧美精品 | 国产一二三区 | A片淫色网站 | 黄色片在线 | 亚洲伦理一区 | 三级视频网址网站 | 免费成人a黄 | 岛国片欧美一级毛 | 在线观看日韩网站 | 国产第三区门 | 波多野吉衣一区 | 国产熟女视频在线 | 超清高清完整版 | 人人爽人人插 | 福利理论片影院 | 国产免费视频网站 | 一区二区国产黄片 | 欧美一区不卡 | 深夜毛片影院 | 理伦片免费 | 在线看片网站日韩 | 无码人妻视频看看 | 激情性爱五月天 | 久久99热精品 | 日欧美在线 | 日韩区在线观看 | 在线91视频 | 免费黄色毛片 | 三级黄色视频 | 久草蜜桃 | 日韩中文字幕观看 | 青青草资源 | 麻豆av在线日韩 | 日韩无码中文字幕 | 日韩欧美大陆另类 | 自拍无码视频亚洲 | 亚洲欧国国产精选 | 美女深夜福利导航 | 很很撸无码岛国片 | 成人短视频大全 | 国产原创在线播放 | 91青青青草视频 | 日本高清影视 | 青青操青青摸 | 东京热不卡 | 亚洲综合无码高清 | 亚洲欧美中文字幕 | 日本兔费四区 | 国产在线视频自拍 | 欧美性爱肏屄图 | 国产a级理论 | 91在线影院 | 国产精品无码免费 | 91自拍网 | 日韩免费网站 | 日本爽快片100 | 可以看的黄色网址 | 亚洲tv黄| 国产一区第二页 | 国产青青草原 | 男男福A级 | 国产中文字幕免费 | 国内精品视频一区 | 伦理影视 | 日韩欧美第一页 | 成人无码短视频 | 国产国内在线 | 日韩在线视频免费 | 日韩在线精品视频 | 91成人福利| 国产福利精品无码 | 操干撸射 | 日韩成人电影无码 | 亚洲欧国国产精选 | 福利中文字幕 | 欧美视频在线视频 | 成人肏逼网 | 东京热综合网 | 91超碰青青 | 欧美性天天 | 超碰色色网 | 激情伊人五月天 | 伦理片软件 | 国产美女视频免费 | 丝瓜视频91 | 欧美福利一二三四 | 欧美亚洲视频 | 日本高清69| 亚州人人| 草逼视频线上观看 | 日本乱伦电影网站 | 日本福利在线视频 | 国产在线观看资源 | 国产成人激情视频 | 免费草莓视频 | 中文字幕久毕 | 日韩电影排行榜 | 欧美国产日本综合 | 福利姬黄色网址 | 香港伦理在线观看 | 日本波多野吉衣 | 极品人妻视频二区 | 91免费国产视频 | 欧美黄片二三区 | 国产黄色91| 毛片A片网址 | 91福利社区试看 | 成人无码高潮 | 中文字幕在线视频 | 欧美狠狠淫 | 欧美日韩三级 | 日本高清一二 | 国产精品玖玖玖在 | 国产日产欧产精品 | 欧美欧美色图直播 | 麻豆精品av入口 | 国产日韩亚洲综合 | 日韩欧美大陆 | 欧美的片免费看 | 青青草高清视频 | 爱豆传媒下载 | 狼人狠狠干 |