たまには自分の研究紹介

D. Okanohara, K. Sadakane. "An Online Algorithm for Finding the Longest Previous Factors". In the 16th European Symposium on Algorithms. Sep 2008. to appear. [pdf(draft)]

この研究では文字列を順々に読んでいったとき、各位置で過去に一番長くマッチした部分文字列を報告する問題を扱ってます。圧縮のLZ77法を知っているなら、マッチする部分を見つける部分を解いてます。で、圧縮以外にもいろいろなパターンマッチング問題とか、インデクシングとか、データマイニングとかいろいろなことにこの情報が利用できるということが知られてるみたいです。

で、大抵はハッシュやtrieを組んで履歴を探すんですが、今回対象にするのはテキストが数10GB overとか、すごいでかいデータも扱いたい。で、さぼらず近似ではなく、必ず一番長い文字列を見つけてこいという自ら厳しい問題設定。最悪計算量ももちろん抑えたく、さらにそのインデクスはコンパクトであってほしい。

で、アイディアとしては、実はPrefix Treeをインクリメンタルに構築する際の副産物として、マッチング情報が出てくる（論文自体も元々はCompressed Suffix Treeをインクリメンタルに作る方法として最初やりはじめたのだが、これだけ切り出すと結構きれいな話になったので切り出した）

結論として大体、履歴の約半分のスペースでできて、履歴長nだとlog^3 nぐらいで見つかる。

最終的に得られたアルゴリズムは、何でこれでできるのかはぱっと見わからん。インデクスといっても、持っている情報は履歴の文字を並び替えた配列と、それの2倍の長さのbit array。これらの上でrankやらselect、rmq操作をすると何故かマッチング情報がでてきて、インデクスも正しく更新される。詳しくは読んでみてください。

でアルゴリズム自体は結構単純にまとまったのだが、ちゃんと性能出そうと思うと実装が結構大変だった。

今もまだ、ゴリゴリチューニングしてます。あと１０倍ぐらいは速くなるかなぁ。もう一工夫ぐらい必要か。

---

ついでに紹介。

moriさんが紹介していたsuffix arraysの新しい線形時間保障のアルゴリズム [pdf]。これは実用的にもそこそこ速いが、実装が非常にコンパクトなのがよい。これも要約しすぎていて、最終的には、なんでこれでできるのかわからないのが残った。

最近提案された線形カーネルに対する学習法。とても速いのに、これもすごいコンパクトな実装 [pdf] ( "A dual coordinate descent method for large-scale linear SVM.") shrinkingとか含めてもC++で100行強ぐらいでかけるらしい。

