Jikken-search-engineをPythonで実装するメモ
参照
- 簡単なWebサーチエンジンの作り方 - 加藤 和彦のブログ
http://d.hatena.ne.jp/kzhk/20091202/p2
- Jikken-search-engine - PukiWiki
Java言語を用いて比較的に大きなプログラムの作成を行う.suffix arrayと呼ばれるデータ構造を用いた全文検索用インデックスを作り,それを用いて,Webファイルに対する全文検索エンジンを作成する.
http://www.osss.cs.tsukuba.ac.jp/kato/wiki/kato/index.php?Jikken-search-engine
Suffix Array
1-1 「与えられた文字列のsuffix arrayを作成するプログラムを作成せよ.」
def suffixArray(t): l = len(t) s = [(t[x:l] , x + 1) for x in range(l)] s.sort() suffix_array = [a[1] for a in s] return suffix_array
1-2 「与えられた文字列に対し,その部分文字列を入力し,部分文字列が 出現する全位置を列挙する検索プログラムを作成せよ.(ヒント: suffix array上の2分探索を行う)」
# vim:fileencoding=utf-8 import math import re sa = [] #Suffix Array #SuffixArray生成 def suffixArray(t): global sa l = len(t) sa = [(t[x:l] , x + 1) for x in range(l)] sa.sort() return False #SuffixArrayを部分文字と先端でマッチするまで二分探査 def binarySearch(req): global sa maxi = len(sa) - 1 mini = 0 while mini + 1 != maxi: pnt = int(math.ceil(float(mini + maxi) / 2)) data = sa[pnt][0] p = re.compile(req) match = p.match(data) if match != None: rangeSearch(mini, maxi, pnt, p) break elif req < data: maxi = pnt else: mini = pnt return False #二分探索でマッチしたポイントから更に二方向に二分探索し、部分文字のある範囲を調べる def rangeSearch(mini, maxi, pnt, p): global sa mini_con = pnt while mini_con + 1 != maxi: pnt_con = int(math.ceil(float(mini_con + maxi) / 2)) data = sa[pnt_con][0] match = p.match(data) if match != None: mini_con = pnt_con else: maxi = pnt_con maxi_lim = mini_con maxi = pnt - 1 while mini + 1 != maxi: pnt = int(math.ceil(float(mini + maxi) / 2)) data = sa[pnt][0] match = p.match(data) if match != None: maxi = pnt else: mini = pnt mini_lim = maxi cnt = [sa[a][1] for a in xrange(mini_lim, maxi_lim + 1)] cnt.sort() print cnt def main(): uri = 'abcdefghiabcjklmnabc' req = 'abc' #部分文字 suffixArray(t) binarySearch(req) if __name__ == '__main__': main()
1-3 「指定された1個のHTMLテキストファイルをメモリ中に読み込んで1個の文字列とし,それに対する suffix arrayをメモリ中に作成し,ユーザから入力された文字列を検索して,入力文字列が出現する全位置を列挙するプログラムを作成せよ.」
# vim:fileencoding=utf-8 import math import re import urllib2 ''' (1-2) ''' def httpget(uri): opener = urllib2.build_opener() doc = opener.open(uri).read() return doc def main(): uri = 'http://www.osss.is.tsukuba.ac.jp/jikken-3nen/codeconv/CodeConvTOC.doc .html' req = 'for' #部分文字 t = httpget(uri) suffixArray(t) binarySearch(req) if __name__ == '__main__': main()
つづく