基於
xml字尾陣列構造演算法
1 引言
xml(extensible markup language)是由w3c開發的乙個標準,xml 1.0是全球接受的規範。xml文件是乙個既包含資料,又包含描述資料結構標記的純文字文件。任何兩個要交換xml資料的應用程式都能進行交換,與平台或程式語言無關。因此,xml在web應用程式開發中得到了廣泛的應用。字尾陣列(suffix array)是乙個簡單,易於編碼且效能良好的資料結構。廣泛應用於文字和計算生物學等領域的字串匹配問題[4,5],包括:(1)burrows-wheeler壓縮演算法;(2)構造簡潔且被壓縮的索引;(3)在web查詢中對使用者的查詢結果進行聚類;(4)用於計算生物學中的基因組分析。本文在構建xml文件索引機制的基礎之上,介紹了一種簡單易行且高效的字尾陣列構造方法。
2 基於xml字尾陣列構造演算法
構造基於
xml字尾陣列一般分為兩步:
(
1)建立xml文件的索引;
(
2)構建索引的字尾陣列;
下面詳細說明這兩個過程。
2.1 xml文件索引機制的建立
在[1]
「書標記「為例來說明xml文件索引機制的建立規則:
23124
software engineering
angela yochem
56
10
有關xml合法性規則參見
。對於xml格式的資料,標籤經常描述實體的屬性名,計量單位等特性,而pcdata中則經常描述的是各種重要的數值。結束標籤在邏輯上僅僅表示乙個資訊單位的結束。因此,在xml格式文件中建立索引的位置有:
(1)
每個開始標籤「字「,如
book,sn
(2)
在開始標籤中所含的每個由空格分開的「字「或「短語「,如
currenty
(3)
pcdata中的「每個字元「,例如與之間的每個字元都應建立索引,以便能迅速找到包含在它中的任乙個字串子集。
在上例中若使用者輸入查詢關鍵字
」book」,則查詢器應輸出位於和之間的全部內容;若使用者輸入查詢關鍵字「unit」,則應顯示。
用上面提出的3條規則對xml文件建立索引,上面的「書標記」xml文件索引為:book,sn,author,software,engineering, price,unit,sum。
2.2 字尾陣列的構造演算法
為了便於理解該演算法,首先來看幾個定義[2]:
定義1
字尾陣列(
suffix array)是字串處理應用中使用的各種資料結構的基礎。s'表示在字符集∑上的乙個字串,$
∑是唯一的終結符且小於字符集∑中的任一字元,s=s'$是在字串s'的末尾加上終結符得到的乙個新字串,如果|s|表示字串的長度,s[i]表示s的第i個字元,那麼suffi=s[i]s[i+1]…s[|s|]是字串s的第i個字尾陣列。例如:s'=「asdfgh」,在其後增加乙個結束符$,得到s=「asdfgh$」,那麼,s2=「dfgh$」是s的第2個字尾陣列。
定義2
索引陣列i(index array): 描述字尾陣列位置的陣列。如果陣列i[0..n]是字尾陣列si的索引陣列,那麼,在i中定義了字尾陣列si在排序過程中的位置變化。其值是通過對字尾陣列中的字串的前k個字元比較得出的長度小於k的字尾順序,因此,必須滿足以下3個條件:
1)若
0〈=l〈k, x[i..i+l-1]=x[j..j+l-1]且x[i+l]k sj;
2)
若0〈=l〈k, x[i..i+l-1]=x[j..j+l-1]且x[i..i+k-1]=x[j..j+k-1],則si=k sj;
3)
若0〈=l〈k, x[i..i+l-1]=x[j..j+l-1]且x[i+l]>x[j+l],則si>k sj;
定義3
訊號陣列v(signal array):是排序進行程度的標誌。v是乙個與s長度相等的陣列,通過該陣列中元素值是否相等來表示排序的結束與否。經過k次迭代後,如果v中存在相等的元素,則將具有相同v值的元素劃分為一組,表明該陣列元素的前k個字元一定是相同的;如果在v中,所有元素均不相等,則表示字串已經有序,排序過程結束。因此,該陣列必須滿足以下的三個條件:
1) 若xi
j,則 v[i]<=v[j];
2) 若xi>xj, 則 v[i]>=v[j];
3) 若xi!=xj,則 v[i]!=v[j];
定義4
規模陣列l (size array):表示該組元素規模的陣列,為了提高排序演算法的時間效能而引入的。對於無序組l[f]=i[f..g]=g-f+1;對於有序的組:l[f]=i[f..g]=-(g-f+1)。
為了提高演算法的空間複雜度,必須更新每乙個陣列的值,在進行第
j次排序時,k=2j-1,表示用小於k的次序來遍歷所有的分組,第一組以索引0開始,元素個數表示為l[0],用v[s+k]對組 i[0..size-1]中的字尾進行排序;下一組從索引g=size處開始,對組i[g..g+s[g]-1]中的字尾進行排序;當遍歷了所有不同的分組後,將其劃分為小於2k有序,如果同一分組g中連續的i[i]和i[i+1]具有不同的值,即v[i[i]+k]!=v[i[i+1]+k],則在索引i和i+1之間劃分分組,同時更新每一分組中元素的個數,最後,更新v[i[i]]的值。
2.3 構造演算法的步驟如下:
1) 通過第乙個字元對si進行排序,初始化各陣列的值;
2)對於j=1,k=21-1=1,用基於比較的排序演算法對在同一組中無序的元素用第二個字元進行排序;
3) 劃分分組並更新陣列v;
4) 將連續的有序分組合併為乙個分組;
5) 如果l中的元素值的絕對值等於所有元素個數n,則說明所有元素已經有序,排序過程結束;
6) 否則,j=j+1;k=2j-1=2*k;轉向[2];
3 演算法的例項與實驗結果分析
3.1 演算法的例項
以s=「upcfpsopuupcf$」為例,構造其字尾陣列的過程如表1所示:
表1:構造s的字尾陣列
kki
xi0
01 2 3
45 6 7 8 9 10 11 12 13
u up c f p
s o p u u p c f $
i[iv[i[i]+k]]
s[l[i]
v[v[i[i]]
1313211
3 12 6 1 4 7 10 5 0 8 9
-1-1 2 2 -1 4 -1 3
0 1 1
3 3
5 6 6 6 6 10 11 11 11
1vv[i[i]+k]]
i[i[i]
s[l[i]
v[v[i[i]]
3 3 6 0 1 10
11 1 6 11 6
2 11 12 3 1 10
4 7 0 9 8
-1-12 -3 2 -3 2 -1
1 1 3 4 6 6 8 9 11 11 13
222v v[i[i]+k]]
i[i[i]
s[l[i]
v[v[i[i]]
8 0
4 3 1 1
11 2 10 1 0 9
-1-11 2
-1
1 2 6 7 11
11444
vv[[i[i]+k]]
i[i[i]
s[l[i]
v[v[i[i]]
8 0
9 0
-1-14
11 12
i[i1313 11 212 3 6 10
1 4 7 5 9 0 8
s的字尾陣列為[13,11,2,12,3,6,10,1,4,7,5,9,0,8]。
3.2實驗結果
在intel(r) 4 cpu,256mb記憶體的計算機上,用本文介紹的方法對3個不同大小的xml文件建立字尾陣列並在此基礎上進行搜尋,執行結果如表2所示: 表
2執行結果
檔案(byte)
構造索引的時間(s)
構造字尾陣列的時間(s)
檢索時間
492,644
1119
13951
<1
884,579
3360
44504
<0.1
1,822,577
13481
203571
<0.1
實驗結果表明:隨著文件的逐漸增大,該構造演算法的效能更優。對於體積為
n的文字檔案,該演算法的空間複雜度是5n,時間複雜度為o(nlogn)。
4 結論
本文在提出建立xml文件索引機制的基礎上,介紹了一種快速構造字尾陣列的演算法,並以實驗表明了該演算法適用於xml文件,為開發基於xml文件的web搜尋引擎提供了一種方案。如何快速的構造個別字元修改的索引檔案的字尾陣列是下一步的研究方向。
c08 基礎,陣列構造演算法
1.sizeof hello 6 放入常量區,編譯器不用頻繁讀取記憶體 2.sizeof 型別 只關心型別而不關心內容 int i 0 sizeof 1 i 4 編譯執行正常 3.只有有型別的指標才能通過指標值確定指標指向的內容 4.陣列的引用 int p 10 int a 10 不使用 5.voi...
Python陣列構造的坑
今天寫python 的時候遇到了乙個大坑 問題是這樣的,我需要建立乙個二維陣列,如下 m n 3test 0 m nprint test test 輸出結果如下 test 0,0,0 0,0,0 0,0,0 是不是看起來沒有一點問題?一開始我也是這麼覺得的,以為是我其他地方用錯了什麼函式,結果這麼一...
c 動態陣列構造及應用
檔名稱 arrayclass.h 功能 自定義陣列型別標頭檔案 用於動態陣列應用,char型別指標陣列 by adengou 2011.8.13 檔案頭 ifndef array class define array class include include ifndef null const i...