suffix array構築するぜ〜的なライブラリは数あれど、unicode文字列を検索したりいろいろするようなライブラリが無いので、せっかくだから作った。富豪的にメモリは一杯あること前提での実装で、mmapとかもしてないけど新聞記事一年分とか突っ込んでもメモリ250MB位だから問題ないよね。手早くやりたいことやるために作ったのでD+ジーに大きく依存しています。suffix arrayの構築や検索はC++で行なっているので高速に動作します。
python2.6以上で、3系は今は動きません。
windows用バイナリはそのうち用意します。
pip install pykwic
基本的に、一行なり一文、一段落を一要素として追加しsuffix arrayを構築します。要素をまたぐような文字列は検索されません。現在は、idなどを保持するようにはなっておらず、単純にkwicのような機能のみを提供しています。
import pykwic kwic = pykwic.Kwic() kwic.add_line(u"うなぎうなうなうなぎなう") kwic.add_line(u"うらにはにわにわとりがいる") kwic.build() kwic.save("ファイル名") kwic.load("ファイル名")
buildを実行すると、suffix arrayが構築され、saveでインデックスを保存することができます。loadも可能です。
searchメソッドでは、検索文字列が存在する場所のprefixと、検索文字列を含むsuffixを取得できます。kwic的な事をするには、以下のような呼出を行えば可能です。
query = u"うな" for x in kwic.search(query): print x[0],query,x[1][len(query):]
せっかくなので、拡張接尾辞配列もサポートしています。 差し当たり、以下のようなコードで二回以上出現する極大部分文字列をその頻度とセットで取り出すことが可能です。頻度は、極大部分文字列として出現した頻度ではなく、文字列の単純な頻度です。 maxmal_substringメソッドはジェネレータになっていて、極大部分文字列を一つずつ取り出すような実装になっています。
kwic = pykwic.EKwic() kwic.add_line(u"うなぎうなうなうなぎなう") kwic.add_line(u"うらにはにわにわとりがいる") kwic.build() for maxsubst in kwic.maxmal_substring(): print maxsubst[0],maxsubst[1]
おもちゃのようなコードですが、ちょっとした用例検索などに利用してください。 そのうちpure cythonに直して便利にします。
コード。非常に有用なのでコピペしてお使いください。
import pykwic kwic = pykwic.Kwic() text=u""" ルイズ!ルイズ!ルイズ!ルイズぅぅうううわぁああああああああああああああああああああああん!!! あぁああああ…ああ…あっあっー!あぁああああああ!!!ルイズルイズルイズぅううぁわぁああああ!!! あぁクンカクンカ!クンカクンカ!スーハースーハー!スーハースーハー!いい匂いだなぁ…くんくん んはぁっ!ルイズ・フランソワーズたんの桃色ブロンドの髪をクンカクンカしたいお!クンカクンカ!あぁあ!! 間違えた!モフモフしたいお!モフモフ!モフモフ!髪髪モフモフ!カリカリモフモフ…きゅんきゅんきゅい!! 小説12巻のルイズたんかわいかったよぅ!!あぁぁああ…あああ…あっあぁああああ!!ふぁぁあああんんっ!! アニメ2期放送されて良かったねルイズたん!あぁあああああ!かわいい!ルイズたん!かわいい!あっああぁああ! コミック2巻も発売されて嬉し…いやぁああああああ!!!にゃああああああああん!!ぎゃああああああああ!! ぐあああああああああああ!!!コミックなんて現実じゃない!!!!あ…小説もアニメもよく考えたら… ル イ ズ ち ゃ ん は 現実 じ ゃ な い?にゃあああああああああああああん!!うぁああああああああああ!! そんなぁああああああ!!いやぁぁぁあああああああああ!!はぁああああああん!!ハルケギニアぁああああ!! この!ちきしょー!やめてやる!!現実なんかやめ…て…え!?見…てる?表紙絵のルイズちゃんが僕を見てる? 表紙絵のルイズちゃんが僕を見てるぞ!ルイズちゃんが僕を見てるぞ!挿絵のルイズちゃんが僕を見てるぞ!! アニメのルイズちゃんが僕に話しかけてるぞ!!!よかった…世の中まだまだ捨てたモンじゃないんだねっ! いやっほぉおおおおおおお!!!僕にはルイズちゃんがいる!!やったよケティ!!ひとりでできるもん!!! あ、コミックのルイズちゃああああああああああああああん!!いやぁあああああああああああああああ!!!! あっあんああっああんあアン様ぁあ!!シ、シエスター!!アンリエッタぁああああああ!!!タバサァぁあああ!! ううっうぅうう!!俺の想いよルイズへ届け!!ハルケギニアのルイズへ届け! """ for line in text.split("\n"): kwic.add_line(line) kwic.build() query=u"クンカ" for res in kwic.search(query): print res[0][-10:].rjust(10,u" "),' ',query,' ',res[1][len(query):20]
結果
あぁ クンカ クンカ!クンカクンカ!スーハースー あぁクンカ クンカ !クンカクンカ!スーハースーハー! あぁクンカクンカ! クンカ クンカ!スーハースーハー!スーハー クンカクンカ!クンカ クンカ !スーハースーハー!スーハースーハ の桃色ブロンドの髪を クンカ クンカしたいお!クンカクンカ!あぁ ブロンドの髪をクンカ クンカ したいお!クンカクンカ!あぁあ!! ンカクンカしたいお! クンカ クンカ!あぁあ!! ンカしたいお!クンカ クンカ !あぁあ!!