ie945264 的部落格

[Term Project] 字串與樣式比對演算法 (資工二乙 494512645 黃奕勳 )

"

        文件在現代中無所不在,它們用來傳遞並發布訊息。從演算法設計的角度來看,這類的文件可視為簡單的字串。也就是說,它們可以抽象地看成一連串構成內容的字元。因此,要在這類資料上進行有趣的搜尋與處理,我們需要有效率的發法來處理字串

         字串搜尋本身不難,使用暴力法也可以求解,但如何快速搜尋字串就不簡單了,傳統的字串搜尋是從關鍵字與字串的開頭開始比對。

[@more@]

Boyer-Moore 演算法

Boyer-Moore字串核對關鍵字的後面開始核對字串,並製作前進表,如果比對不符合則依前進表中的值前進至下一個核對處,假設是p好了,然後比對字串中p-n+1p的值是否與關鍵字相同。

 

那麼前進表該如何前進,舉個實際的例子,如果要在字串中搜尋JUST這個字串,則可能遇到的幾個情況如下所示:

依照這個例子,可以決定出我們的前進值表如下:

其它

J

U

S

T

4

3

2

1

4match

 

如果關鍵字中有重複出現的字元,則前進值就會有兩個以上的值,此時則取前進值較小的值,如此就不會跳過可能的位置,例如texture這個關鍵字,t的前 進值應該取後面的3而不是取前面的7

 我們將last(c)定義如下:

如果P包含c,則last(c)就是c出現在P之中最後一個位置(最右方)的索引值。否則,我們直接定義last(c) = -1

 Algorithm BMMatch(T,P)   InputStrings T (text) with n characters and P (pattern) with m characters   OutputStrings index of the first substring of T matching P , or an indication that P is not a substring of T

   compute function last

   i m-1   j m-1   repeat      if P[j] = T[i] then         if j = 0 then            return i                   //a match!         else            i i-1            j j-1      else         i i+m-min( j,1+last(T[i]) )                        //jump step         j m-1   until i n-1   return There is no substring of T matching P. 

Knuth-Morris-Pratt 演算法

KMP演算法是拿來處理字串是否相符。換句話說,給你兩個字串,你需要回答,B字串是否是A字串的子字串(A字串是否包含B字串)。比如,字串A="I'm matrix67",字串B="matrix",我們就說BA的子字串。  解決這類問題,通常我們的方法是枚舉從A字串的什麼位置起開始與B字串比對,然後驗證是否相符。假如A字串長度為nB字串長度為m,那麼這種方法的複雜度是O (mn)。雖然很多時候複雜度達不到mn(驗證時只看頭一兩個字母就發現不相符了),但我們有許多「最壞情況」,比如,A= "aaaaaaaaaaaaaaaaaaaaaaaaaab"B="aaaaaaaab"我們將介紹的是一種最壞情況下O(n)的算法(這裡假設 m<=n),即KMP演算法之所以叫做KMP,是因為這個算法是由KnuthMorrisPratt三個提出來的,取了這三個人的名字的頭一個字母.假如,A="abababaababacb"B="ababacb"。我們用ij分別表示,A[i-j+ 1..i]B[1..j]完全相等。也就是說,i是不斷增加的,隨著i的增加j相應地變化,且j滿足以A[i]結尾的長度為j的字串正好相對於B字串的前 j個字元(j當然越大越好),現在需要檢驗A[i+1]B[j+1]的關係。當A[i+1]=B[j+1]時,ij各加一;什麼時候j=m了,我們就說BA的子字串,並且可以根據這時的i值算出相對的位置。當A[i+1]B[j+1]KMP的策略是調整j的位置 (減小j值)使得A[i-j+1..i]B[1..j]保持匹配且新的B[j+1]恰好與A[i+1]匹配(從而使得ij能繼續增加)。我們看一看當 i=j=5時的情況。

       i = 1 2 3 4 5 6 7 8 9 ……
       A = a b a b a b a a b a b …
       B = a b a b a c b
       j = 1 2 3 4 5 6 7
       此時,A[6]B[6]。這表明,此時j不能等於5了,我們要把j改成比它小的值j'j'可能是多少呢?仔細想一下,我們發現,j'必須要使得B[1..j]中的頭j'個字母和末j'個字母完全相等(這樣j變成了j'後才能繼續保持ij的性質)。這個j'當然要越大越好。在這裡,B [1..5]="ababa",頭3個字母和末3個字母都是"aba"。而當新的j3時,A[6]恰好和B[4]相等。於是,i變成了6,而j則變成了 4


       i = 1 2 3 4 5 6 7 8 9 ……
       A = a b a b a b a a b a b …
       B =           a b a b a c b
       j =           1 2 3 4 5 6 7
        從上面的這個例子,我們可以看到,新的j可以取多少與i無關,只與B字串有關。我們完全可以預處理出這樣一個數組P[j],表示當匹配到B數組的第j個字母而第j+1個字母不能匹配了時,新的j最大是多少。P[j]應該是所有B[1..P[j]]=B[j-P[j]+1..j]的最大值。再後來,A[7]=B[5]ij又各增加1。這時,又出現了A[i+1]B[j+1]的情況:       i = 1 2 3 4 5 6 7 8 9 ……       A = a b a b a b a a b a b …       B =           a b a b a c b       j =           1 2 3 4 5 6 7      由於P[5]=3,因此新的j=3        i = 1 2 3 4 5 6 7 8 9 ……       A = a b a b a b a a b a b …       B =                  a b a b a c b       j =                  1 2 3 4 5 6 7      這時,新的j=3仍然不能滿足A[i+1]=B[j+1],此時我們再次減小j值,將j再次更新為P[3]        i = 1 2 3 4 5 6 7 8 9 ……       A = a b a b a b a a b a b …       B =                   a b a b a c b       j =                    1 2 3 4 5 6 7       現在,i還是7j已經變成1了。而此時A[8]居然仍然不等於B[j+1]。這樣,j必須減小到B[1],即0        i = 1 2 3 4 5 6 7 8 9 ……
       A = a b a b a b a a b a b …
       B =                            a b a b a c b
       j =                     0 1 2 3 4 5 6 7
       終於,A[8]=B[1]i變為8j1。事實上,有可能j到了0仍然不能滿足A[i+1]=B[j+1](比如A[8]="d"時)。因此,準確的說法是,當j=0了時,我們增加i值但忽略j直到出現A[i]=B[1]為止。      這個過程的代碼,我們在這裡列出:程式代碼j:=0;
for i:=1 to n do
begin
      while (j>0) and (B[j+1]
A[i]) do j:=P[j];
      if B[j+1]=A[i] then j:=j+1;
      if j=m then
      begin
         writeln('Pattern occurs with shift ',i-m);
         j:=B[j];
      end;
end;

最後的j:=P[j]是為了讓程式繼續做下去,因為我們有可能找到多處相符。    這個程式或許比想像中的要簡單,因為對於i值的不斷增加,程式碼用的是for迴圈。因此,這個程式虛擬碼可以這樣形象地理解:掃瞄字串A,並更新可以相對到B的什麼位置。       為什麼這個程式是O(n)的?其實,主要的爭議在於,while迴圈使得執行次數出現了不確定因素。我們將用到時間複雜度的攤還分析中的主要策略,簡單地說就是通過觀察某一個變量或函數值的變化來對零散的、雜亂的、不規則的執行次數進行累計。KMP的時間複雜度分析可謂攤還分析的典型。 我們從上述程式的j值入手。每一次執行while迴圈都會使j減小(但不能減成負的),而另外的改變j值的地方只有第五行。每次執行了這一行,j都只能加1;因此,整個過程中j最多加了n1。於是,j最多只有n次減小的機會(j值減小的次數當然不能超過n,因為j永遠是非負整數)。這告訴我們,while迴圈總共最多執行 了n次。按照攤還分析的說法,平攤到每次for迴圈中後,一次for迴圈的複雜度為O(1)。整個過程顯然是O(n)的。這樣的分析對於後面P數組預備處理的過程同樣有效,同樣可以得到預處理過程的複雜度為O(m)      預備處理不需要按照P的定義寫成O(m^2)甚至O(m^3)的。 我們可以P[1],P[2],...,P[j-1]的值來獲得P[j]的值。對於剛才的B="ababacb",假如我們已經求出了P[1],P[2],P[3]P[4],我們應該怎麼求出P[5]P[6]P[4]=2,那麼P [5]顯然等於P[4]+1,因為由P[4]可以知道,B[1,2]已經和B[3,4]相等了,現在又有B[3]=B[5],所以P[5]可以由P[4] 後面加一個字元得到。P[6]也等於P[5]+1嗎?顯然不是,因為B[ P[5]+1 ]B[6]。那麼,我們要考慮「退一步」了。我們考慮P[6]是否有可能由P[5]的情況所包含的子字串得到,即是否P[6]=P[ P[5] ]+1下面為簡易說明:               1 2 3 4 5 6 7
       B = a b a b a c b
       P = 0 0 1 2 3 ?
       P[5]=3是因為B[1..3]B[3...5]都是"aba";而P[3]=1則告訴我們,B[1]B[5]都是"a"。既然P[6]不能由P[5]得到,或許可以由P[3]得到(如果B[2]恰好和B[6]相等的話,P[6]就等於P[3]+1了)。顯然,P[6]也不能通過P[3]得到,因為B[2]B[6]。事實上,這樣一直推到P[1]也不行,最後,我們得到,P[6]=0      怎麼這個預先處理過程跟前面的KMP主程式這麼像呢?其實,KMP的預先處理本身就是一個B字串「自我配對」的過程。  它的代碼和上面的代碼神似:程式代碼P[1]:=0;
j:=0;
for i:=2 to m do
begin
      while (j>0) and (B[j+1]
B[i]) do j:=P[j];
      if B[j+1]=B[i] then j:=j+1;
      P[i]:=j;
end;
       最後補充一點:由於KMP算法只預先處理B字串,因此這種算法很適合這樣的問題:給定一個B字串和一群不同的A字串,問B是哪些A字串的子字串。"

Huffman Coding

"

哈夫曼編碼(Huffman Coding)是一種編碼方式,而哈夫曼樹又稱最優二元樹,是一種帶權路徑長度最短的二元樹,經常應用於數據壓縮。

Huffman Coding是一種一致性編碼法,用於無損數據壓縮的熵編碼(權編碼)演算法。他是使用一張特殊的編碼表將原本來源字元(例如某文件中的一個符號)進行編碼。而這張編碼表是根據每一個字元出現的機率而去計算出來的,出現機率較高的字元使用較短的編碼,出現機率較低的則使用較長的編碼。這種編碼方式可以使編碼後的字元串的長度降低,也不會損害到壓縮數據。這種方法是由David.A.Huffman發展起來的。

例如,在一段字元串中,a的出現機率很高,而b的出現機率則最低。當用Huffman Coding對他進行編碼時,a極有可能用1bit來表示,而z則可能花去25bit

Huffman Tree的建立方式則是在編碼表中找出現機率最低的兩個字元,較低的放left node,較高的放right node。將兩個node出現次數相加當作parent node的值,再放入編碼表中比較。重複這個動作到全部字元已經在tree中,將往左的路徑取0,往右的路徑取1,從root到字元的路徑為該字元的新編碼。

參考資料 演算法課本
資料來源 http://zh.wikipedia.org/w/index.php?title=%E5%93%88%E5%A4%AB%E6%9B%BC%E7%BC%96%E7%A0%81&variant=zh-tw

"

Greedy Algorithm

貪婪演算法簡介
1. 一種短視/近利/偷懶/貪婪的想法。
2. 每一步都不管大局,只求局部解決方法。
3. 它透過一步步的選擇局部最佳解來得到問題的解答。
4. 它所做的每一個選擇是根據某種準則來決定的,而且前後次的決定並無關聯性。
5. 它用來解決最佳化問題時,通常很有效率且簡單。
6. 它並不能解決所有最佳化問題,例如:最短路徑問題。
貪婪演算法的演算過程
重複下列步驟直到找出解答為止:
選擇程序 => 你事先設計好一個挑選局部最佳解的規則,並用它來挑選下一個要加入解集合的項目。
可行性檢查 => 檢查新的解集合是否符合題目限制。
解答檢查 => 檢查新的解集合是否已經是正確的結果。

資料來源:http://mail.sju.edu.tw/~cm/course/alg/ch3-Greedy.pdf

RSA:簡介

RSA:簡介
加密系統可區分為二類:對等〈symmetric〉以及公鑰

對等〈又稱做秘密金鑰〉加密系統的概念相當簡單:使用一組金鑰將訊息的內容加密後
傳送給對方。用來加密訊息的演算可能是一項眾所周知的標準,例如DES或AES,但
只有持有原始金鑰的收件人才能解出原始訊息的內容。沒有金鑰的收件者僅能看到一堆無意義的亂碼。

RSA 加密法採用C = Me mod n的演算公式,解密公式為M = Cd mod n,其中的M是純
文字訊息,而C是加密後的訊息內容。值得注意的是加密與解密皆採用稱為模指數運算
〈modular exponentiation〉的基本公式。

這項系統的安全性源自於模指數運算的參數。公開的指數〈e〉必須是一個質數,但可
以任意選用,最常選用的是17。模數〈n〉必須是兩個質數的乘積〈通常稱為p 與q〉。
指數〈d〉則由p、q、以及e 推算而得。

提升RSA的運算速度: Montgomery 演算法
傳統模指數運算〈modular exponentiation〉皆採用重複的除法演算模式。由於除法本身
的運算速度較為遲緩,尤其是除數與被除數極大時,其計算速度更是緩慢,因此RSA
加密與解密一直都是較緩慢的處理程序。
在1985年,研究專家Peter Montgomery發明一套結合乘法與移位的運算法,取代原先
的除法計算模式。這項發明大幅提高運算速度,成為現今廣為採用的RSA解密運算法。

參考資料:http://home.educities.edu.tw/dzjsjgl/rsa.pdf

PageRank

PageRank,網頁排名,又稱網頁級別、Google左側排名或佩奇排名。PageRank™是以公司創辦人拉里·佩奇(Larry Page)命名。是一種由搜索引擎根據網頁之間相互的超連結計算的網頁排名。它經常和搜索引擎優化有關。PageRank系統被Google用來體現網頁的相關性和重要性。Google的創始人拉里·佩奇和謝爾蓋·布林1998年在史丹福大學發明了這項技術。

  PageRank通過網路浩瀚的超連結來往來確定一個頁面的等級。Google把從A頁面到B頁面的連結解釋為A頁面給B頁面投票Google根據投票來源(甚至來源的來源,即連結到A頁面的頁面)和投票目標的等級來決定新的等級,簡單的說,一個高等級的頁面可以使其他低等級頁面的等級提升。

簡單的來說:網站連結進來的數量,愈多,當然愈好。外部連結網站自己的PageRank,愈高愈好。外部連結網站連結出去的數量,越低越好。 
 
 

如何提高PageRank?
 
  瘋狂登錄:將你的資料提供給所有搜尋引擎,這樣最起碼PageRank可以向上提升1到2分。

  與朋友互相連結:團結就是力量,你有網站、我也有,只要兩個人的網站互連,就會彼此受惠,PageRank都會提高「一點點」,何樂而不為,而且互相拉抬之後,如果朋友的網站PageRank因此提高,從他那邊分過來的分數也會提高,但也切勿漫無目的隨意內容相差太多的網站,否則可能被當成惡搞。

  提升網站品質:只要你的網站資料豐富、有趣,不用要求也會有人主動連結,這是經營網站的本質,也是確保PageRank的重要手段。

常用的backtracking結構及概念

"

backtracking 的概念是指從一個問題中,挑出一個或多個符合這個問題限制的序列。例如有名的N后問題:在 nxn 的棋盤上,挑出一個 n個皇后不會相互攻擊的序列。

之前看過一個考題:給定一數列和一常數,設計一演算法能找出子數列合等於這個常數的序列。
在還不知這就是 sum of subset 問題的時候,想了很久,除了暴力法(做power set,檢查所有組合),想不出有什麼更好的方法;後來過了一段蠻長的時間,才在偶然間念書的時候看到 backtracking 用來解這類問題。其實用 backtracking 用的方法也是列舉所有的情況,不過美妙之處在於它能對所有須考濾的情況做適當的過濾,於是你並不須要嚐試所有的可能組合,就可以得到解答。

backtracking 的技巧就是樹形結構的 depth first search 演算法變形,用遞迴來走訪問題的狀態空間樹。它本身字面上的意思是指:例如走迷宮,當我們遇到死路時,就必須退回到上一個叉路,嚐試另一條路;若我們能夠在還沒繼續走訪之前,就能知道前面的路是死路,這就是上面說的”過濾”。

這類的問題,在最抽像、最頂層的意義是我們可以把問題中所有可能的組合,當成樹形結構的所有節點,每個節點對應到一種組合。透過問題所給的限制,或是問題中隱含的資訊,我們可以適度的排除某些節點不去走訪,因此我們不須走訪所有節點,因此我們只要考濾部份組合就能得到答案。例如八后問題,若第一個皇后擺在(1,1)的位置,則接下來的皇后都不須考濾(n,1)與(n,n)的位置,這就是修剪狀態空間樹。

大部份的 backtracking 有一個固定的結構,它看起來像是這樣:

void checkNode(node n)
{
 node u;

 if ( 前面還有路 )
  if ( 是出口 )
   印出答案;
  else
   for ( 對於 n 下面的 u 條叉路 )
    checkNode(u);
}

 

http://blog.sina.com.tw/4226/article.php?pbgid=4226&page=1&entryid=16566

"

XmlHttp

"

XmlHttp是什麼?

最通用的定義為:XmlHttp是一套可以在Javascript、VbScript、Jscript等腳本語言中通過http協議傳送或從接收XML及其他數據的一套API。XmlHttp最大的用處是可以更新網頁的部分內容而不需要刷新整個頁面。
來自MSDN的解釋:XmlHttp提供客戶端同http服務器通訊的協議。客戶端可以通過XmlHttp對像(MSXML2.XMLHTTP.3.0)向http服務器發送請求並使用微軟XML文檔對像模型Microsoft? XML Document Object Model (DOM)處理回應。

現在的絕對多數瀏覽器都增加了對XmlHttp的支持,IE中使用ActiveXObject方式創建XmlHttp對象,其他瀏覽器如:Firefox、Opera等通過window.XMLHttpRequest來創建xmlhttp對象。

XmlHttp對像參考:

屬性:

onreadystatechange* 指定當readyState屬性改變時的事件處理句柄。只寫
readyState 返回當前請求的狀態,只讀.
responseBody 將回應信息正文以unsigned byte數組形式返回.只讀
responseStream 以Ado Stream對象的形式返迴響應信息。只讀
responseText 將響應信息作為字符串返回.只讀
responseXML 將響應信息格式化為Xml Document對象並返回,只讀
status 返回當前請求的http狀態碼.只讀
statusText 返回當前請求的響應行狀態,只讀

* 表示此屬性是W3C文檔對像模型的擴展.

方法:

abort 取消當前請求
getAllResponseHeaders 獲取響應的所有http頭
getResponseHeader 從響應信息中獲取指定的http頭
open 創建一個新的http請求,並指定此請求的方法、URL以及驗證信息(用戶名/密碼)
send 發送請求到http服務器並接收回應
setRequestHeader 單獨指定請求的某個http頭

 

資料來源:http://www.infowe.com/xmlhttp/#

"

Semantic Web

"

Semantic Web的概念,是希望透過一個基礎架構,讓資料能在軟體、企業、社群間分享交換。也就是說,要讓Web變得更有意義。在這個技術的支持下, 我們可以把我們要搜索的內容給代理軟件, 由電腦進行負責搜尋. 舉例來說, 在醫院裡面, 如果我們需要配藥. 我們可以直接用我們的PDA連接到醫生的代理端口, 直接找到在家庭住址附近的10公里以內的藥店, 並且藥店已經有該藥品的庫存. 那個藥店還有服務質量反饋等信息. 同時我們可以用網絡來處理病人和醫生各自的日程表, 來安排日程. 這一切的服務全部有軟件代理來進行完成. 這個運算量和交叉信息的搜索是十分驚人的. 它對網絡頁面的人工智能,數據庫的開放限度和兼容性的要求也非常高. 現在,我們已經擁有了這種類似的數據庫,叫做RDF和網絡通用語言(OWL). 現在Yahoo!的最新美食站點已經有了類似的功能. 網站名稱叫做Spivack's Radar Network(Spivack 雷達網)就是由這種技術構成

"

RDF 簡介

"

資源描述結構(Resource Description Framework,簡稱RDF)是由全球資訊網協會(W3C) 主導以及結合多個元資料團體,所發展而成的一個架構,可用來攜帶多種不同的元資料來往於網際網路和WWW上。根據W3C 的RDF工作小組的草案,來對 RDF模型做介紹,基本上RDF是一個與任何特定電腦語法無關的抽象的資料表達模式,用來呈現一個特性還有值。而所謂的「特性」(Property),可能是
資源的屬性:如題名、著者等,資料的題名(Title)欄位即可歸屬於這類。
資源間的關係:如資料的關連(Relation)和來源(Source)兩欄位即屬於這類範疇。
RDF的另外一個特點是語法獨立性,因此兩段看起來差異很大的RDF陳述,事實上可能是描述相同的一件事,這是因為RDF是一個抽象的資料模式。由於這個抽象的特點,各種不同的元資料均可利用此種抽象的資料模式,來表達它們的內容。
參考網址:http://home.kimo.com.tw/gooloo1234/

"

VoiceXML

"VoiceXML(Voice eXtensible Markup Language)是由VoiceXML論壇制定的通過電話訪問Internet網路的標準。1999年3月,由Motorola、Lucent、AT&T、IBM四家公司聯合發起成立了VoiceJML論壇,其目的在於為電話和移動設備提供一種便捷的訪問Internet網路,獲取服務和資訊的手段。2000年3月,VoiceXML論壇發佈了VoiceXML 1.0標準。5月,W3C(World Wide Web Consortium)接受了VoiceXML1.0。目前,國內外共有150多家公司支持VoiceXML,Motorola、Lucent等公司已開發出了基於VoiceXML的產品。

  VoiceXML是W3C定義的可擴展標記語言(XML)的一種擴展,根據播放的提示資訊、口述的命令、要記錄和識別的語音或按鍵音輸入,實現人和電腦之間的交互對話。VoiceXML的標準化將簡化Web上具有語音回應服務的個性化介面的創建,使人們能夠通過語音和電話訪問網站上的資訊和服務。

  VoiceXML的主要目標是希望通過互動式語音介面應用Web上已經有的大量資訊,同時VoiceXML希望能夠將開發人員從最低級的編程和資源處理工作中解放出來。VoiceXML能夠利用人們已經非常熟悉的客戶機(伺服器)方式,將語音服務和資料服務融合起來。

"

訂閱文章