目錄:
- Dictionary Data Structure 詞典數據結構
- Wild-Card Query 通配符查詢
- Spelling Correction 拼寫糾正
- 索引詞(term vocabulary)。
- 文檔頻率(document frequency,即這個詞在多少個文檔里出現)。
- 指向倒排表的指針(pointers to each postings list )。





一棵m 階的B-樹滿足下列特性的m 叉樹:
- 樹中每個結點至多有m 棵子樹;
- 若根結點不是葉子結點,則至少有兩棵子樹;
- 除根結點之外的所有非終端結點至少有[m/2] 棵子樹;
- 所有的非終端結點中包含以下信息數據:(n,A0,K1,A1,K2,…,Kn,An)。其中:Ki(i=1,2,…,n)為關鍵碼,且Ki<Ki+1,Ai 為指向子樹根結點的指針(i=0,1,…,n),且指針Ai-1 所指子樹中所有結點的關鍵碼均小於Ki (i=1,2,…,n),An 所指子樹中所有結點的關鍵碼均大於Kn。n為關鍵碼的個數。
- 所有的葉子結點都出現在同一層次上,並且不帶信息(可以看作是外部結點或查找失敗的結點,實際上這些結點不存在,指向這些結點的指針為空)。
這樣講起來或許比較枯燥難懂,看這張圖就好了:
樹的優點就是可以解決前綴查找的問題了。
缺點是速度比哈希慢點,是O(logM)並且要求是平衡的,重新平衡一棵樹的代價大。(雖然B-樹減輕了這種代價)
Wildcard queries,通配符查詢。
比如查詢語句 mon*:找出所有以mon開頭的單詞。如果采用樹(或者B-樹)結構詞典,我們可以很容易的解決,只需要查詢范圍在mon ≤ w < moo的所有單詞就ok了。
但是查詢語句 *mon:找出所有以mon結尾的單詞就比較困難了。其中一種辦法就是我們增加一個額外的B-樹來存儲所有單詞,以從后向前的順序,然后在這個樹上查詢范圍在nom ≤ w < non的所有單詞。
可是如何處理通配符在單詞中間的查詢呢?
比如query是co*tion的話。我們當然可以分別在B-樹查詢到co*和*tion的所有單詞然后合並這些單詞,但是這樣開銷太大了。
解決辦法就是:輪排索引(Permuterm Index),我們把query的通配符轉換到結尾處。
設置一個標志$表示單詞的結尾。
以hello舉例,hello可以被轉換成hello$, ello$h, llo$he, lo$hel, o$hell。$代表中hello的結束。現在,查詢X等於查詢X$,查詢X*等於查詢X*$,查詢*X等於查詢X$*,查詢X*Y等於查詢Y$X*。對於hel*o來說,X等於hel,Y等於o。
既然我們已經把通配符都弄到了單詞尾部,現在我們又可以通過B-樹像以前那樣查詢拉。
以上,我們已經完成了對query的轉換,那么那些存儲的索引的詞要怎么處理才能配合這種query查詢呢?
我們對索引來建立索引!!
Bigram indexes。就是兩兩個字母來索引。
舉例來說,一個文本是“April is the cruelest month”,分別成Bigram indexes就是“$a,ap,pr,ri,il,l$,$i,is,s$,$t,th,he,e$,$c,cr,ru,ue,el,le,es,st,t$, $m,mo,on,nt,h$”,其中$ 代表着單詞邊界的符號。
那么如何對索引建立索引??
維護第二個倒排表,倒排表的索引詞是Bigram indexes,posting list的值就是與之匹配的dictionary terms。
像這樣:
好了!目前為止,我們既對query進行了處理,也對terms進行了處理。
所以現在如果我們要查詢 mon*,query會被分解成 $m AND mo AND on ,然后從上圖中的倒排表做兩個AND可以得到匹配的terms了!!
但是,我們會發現 $m AND mo AND on 也會匹配到單詞moon,而moon不符合mon*的格式,這是他的一個缺點。我們必須要過濾掉這些詞。
另外,一條查詢語句往往相當多的布爾查詢,這個開銷也挺大的。
Spelling correction,拼寫校正。
我們google一下 Alanis Morisett ,得到結果如圖:
對了,就是這個提示,您找的是不是:xxxxxx。
在搜索引擎中,需要有一個可以查詢到所有正確單詞的詞典。
給定一個詞典和一個query,返回一個和query最接近的words。
怎么用才算是最接近??
- 編輯距離算法。
- 帶權編輯距離算法。
編輯距離(Edit distance):
給定兩個字符串S1和S2,從S1轉換到S2的最小步驟就是他們的編輯距離。這些步驟包括,Insert(1步), Delete(1步), Replace(1步),copy(0步)。
比如說:
dof到dog的編輯距離是1,cat到act的編輯距離是2,cat到dog的編輯距離是3.
算法導論里關於編輯距離的偽代碼如下:
舉例子:算cats到fast的編輯距離~
括號里圈出來的表示實際應該填的值,其他的只是用來進行對比,取其中最小的數。
具體到表中的每一格中四個數字的含義就是:
從左邊的格子過來代表增加,上邊的格子過來代表刪除,斜上角的格子過來代表替換(此時兩個字符不相等)或復制(此時兩個字符不相等)。
編輯距離就是這樣子。那么什么是帶權編輯距離呢?
比如說,我們打字的時候,m被錯打成n的幾率會比m錯打成p的幾率更大,所以我們應該認為m和n的編輯距離小於m到p的編輯距離。因此將m替換為n時計算編輯距離應該比將m替換為p時的編輯距離小。
實現帶權編輯距離,我們需要一個額外的權值矩陣。
那么,給定一個查詢詞,我們是不是得計算這個查詢詞和所有的索引詞之間編輯距離呢?
答案是否定的,因為這樣開銷很大而且慢。
怎么用減少計算呢??
比如說,如果query是lord:
我們只取lo,or,rd中有重疊兩次或以上的term,然后合並這些term,以這個為范圍進行編輯距離的計算。
如果本文對您有一點點的幫助,請幫忙點個贊,十分感謝!~ =。=
如果您有更好的見解或糾正,歡迎您在下面評論指出。