Rubysapporo Stringsearch

1,373 views
1,277 views

Published on

Published in: Technology, Education
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
1,373
On SlideShare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
1
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Rubysapporo Stringsearch

  1. 1. 多バイト文字列の 検索アルゴリズム (株)サイクル・オブ・フィフス 石田朗雄 10/01/30
  2. 2. その前に、、、 ● http://www.local.or.jp/?LDD/LDD10Winter ● LOCAL DEVELOPER DAY '10 /Winter ● 2010/2/13(土) 12:45~18:35 ● 札幌市産業振興センター セミナールームA 10/01/30
  3. 3. 文字列検索 ● PostgreSQLでは ● SELECT strpos('high', 'ig') => 2 ● SELECT strpos('high', 'X') => 0 ● replace(), split_part(), string_to_array() ● Rubyでは ● "high".index("ig") #=> 1 ● "high".index("X") #=> nil ● String#partition, String#include 10/01/30
  4. 4. 文字列検索アルゴリズム ● Boyer-Mooreとその仲間 ● Boyer-Moore – 二種類のskiptable使ったアルゴリズム ● Boyer-Moore-Horspool – 片一方だけでもそこそこ速いんじゃね? – PostgreSQLはコレ ● Sunday Quick Search – 片一方しか使わないんだったら1Byte先を見てもよく ね? – Rubyはコレ 10/01/30
  5. 5. ● 詳しくはWebで!! ● http://www-igm.univ-mlv.fr/~lecroq/string/index.html 10/01/30
  6. 6. skiptableの作り方 'A' 'B' 'C' 'A' 'B' 41 42 43 41 42 s[41] = 5 2 = 2 s[42] = 4 1 = 1 s[43] = 3 = 3 10/01/30
  7. 7. ポイント ● 不一致だった場合に何文字skipできるかは、patternの 末尾の比較対象(+1?)の文字によって決まる ● 簡易実装では、256個の配列でskiptableを持っている ● 日本語どうすんの? ● widecharをつかうとskiptable大きすぎ ● ハッシュではコストが高すぎ ● multibyteのままだと泣き別れが発生する 10/01/30
  8. 8. multibyte/widechar ● マルチバイト ● 可変長 ● ASCII互換 ● EUC-JP、UTF-8 ● ワイド文字 ● 固定長(16bit/32bit) ● ASCII非互換 ● UTF-16(?)、UTF-32 ● 別にUNICODEじゃなくてもいいけどね 10/01/30
  9. 9. PostgreSQLの場合 ● src/backend/utils/adt/varlena.c ● widecharに変換 ● そもそもASCIIでも256個もskiptableいらないんじゃ ね? ● "ABCDEFG"をmod 4して"12301230"と考えても、ス キップする量は減るが成立する ● 文字列の長さでskiptableのサイズを決めている ● http://archives.free.net.ph/message/20080830.232111.faf51 ● http://github.com/postgres/postgres/commit/285966b76c1a 10/01/30
  10. 10. 'あ' 'い' 'う' 'え' 3042 3044 3046 3048 s[3042] = 4 = 4 s[3044] = 3 = 3 s[3046] = 2 = 2 s[3048] = 1 = 1 2 0 2 0 s[0] = 4 2 = 2 s[1] = = 5 s[2] = 3 1 = 1 s[3] = = 5 10/01/30
  11. 11. Rubyの場合 ● string.c:rb_str_index() ? re.c:rb_memsearch() ● マルチバイトのまま検索 ● 短かい文字列/UTF-8の場合/それ以外の場合でアルゴ リズムを分けている ● rb_memsearch_ss:たぶんrabin-karp ● rb_memsearch_qs_utf8 ● rb_memsearch_qs ● 泣き別れたらやりなおせばいいじゃない ● http://article.gmane.org/gmane.comp.lang.ruby.devel/8100 ● http://github.com/shyouhei/ruby/commit/e58adeae0f384a5 10/01/30
  12. 12. rb_memsearch_qs_utf8(1) ● UTF-8では0xe3がやたらとでてくる 'あ' 'い' 'う' e3 81 82 e3 81 84 e3 81 86 s[81] = 8 5 2 = 2 s[82] = 7 = 7 s[84] = 4 = 4 s[86] = 1 = 1 s[e3] = 9 6 3 = 3 10/01/30
  13. 13. rb_memsearch_qs_utf8(2) ● 先頭byteの時は、文字全体からハッシュを計算する 'あ' 'い' 'う' e3 81 82 e3 81 84 e3 81 86 46 48 4a s[46] = 9 = 9 s[48] = 6 = 6 s[4a] = 3 = 3 s[181] = 8 5 2 = 2 s[182] = 7 = 7 s[184] = 4 = 4 s[186] = 1 = 1 10/01/30
  14. 14. Pythonの場合 ● Objects/stringlib/fastsearch.h ● http://effbot.org/zone/stringlib.htm ● Boyer-MooreとBloom Filterの合わせわざらしい ● イニシャルコストとメモリ効率はよさそう ● 長い文字列はどうか ● 但し内部コードはUTF-16(or32)に限る 10/01/30

×