noshi91のメモ (original) (raw)
この広告は、90日以上更新していないブログに表示しています。
問題
文字集合を とする文字列 と がある。 の長さ の連続部分列のそれぞれについて、 にマッチするか判定せよ。 ただし文字列がマッチするとは、それぞれの文字列中の を好きな文字に置き換えたときに両文字列が一致することを指す。
解法 (Clifford & Clifford, 2007 [1])
文字列 と がマッチすることと が同値である。 したがって、各 について を計算できればよい。 これは括弧を展開して積和形にし、それぞれの項については適切な列を FFT を用いて畳み込めばよい。 時間計算量は 。
値域の削減 (Clifford, Efremenko, Porat, & Rothschild, 2009 [2])
前述した解法は最終的に か判定したい値が 程度まで大きくなり得る。
\begin{align} S ' _ i := \begin{cases} 0 \quad & ( S _ i = 0 ) \cr 1 \quad & ( S _ i \neq 0 ) \end{cases} \cr T ' _ i := \begin{cases} 0 \quad & ( T _ i = 0 ) \cr 1 \quad & ( T _ i \neq 0 ) \end{cases} \end{align}
と定義すれば、 で判定しても問題ない。 これで まで削減された。 ちなみに とするとこの値は 以下になる。
乱択
素数 と一様乱数 を用いて、 を判定してもよい。 このとき の各連続部分列について、マッチしていると誤って判定される確率は 以下である。 が大きくても値域の問題が発生しないことと、項を展開すると つしかないため畳み込みの回数が減るという利点がある。
巡回畳み込みを用いた高速化
これらのアルゴリズム内では、 を各 について求めるために畳み込みを用いる。 これは を反転して通常の畳み込みを行えばよいのだが、畳み込んだ結果のうち先頭 項と末尾 項は必要がない。 よって巡回畳み込みでこれらの部分が重なっても問題なく、畳み込みの長さを短くすることができる。
線形性を用いた高速化
アルゴリズム中では 回の畳み込みを行い、その和だけに興味がある。 よってそれぞれの畳み込みにおいて IDFT を行わず、全部足し合わせて最後に 度だけ IDFT を行うことで定数倍高速化になる。ボトルネックには関係ないと思われるが、IDFT の後の規格化も非零判定だけなので必要ない。
ワイルドカードが一方のみにある場合の高速化
側にワイルドカードがない場合、常に である。 すると を積和形にした際に現れる つの項の内 つは に依存しない値になり、その総和は定数となる。 側にワイルドカードがない場合も同様の議論により、累積和で つの項は計算できる。 前述した乱択の場合も、 つの畳み込みが つに削減される。
の場合の高速化
判定するべき連続部分列のうち最初の 個を判定するためには の先頭 文字があれば十分であり、これを切り出して今までのアルゴリズムを適用すれば で判定できる。 この調子で 個ずつ判定すると全体で となる。 一度に判定する量は の何倍かの範囲で調整した方が定数倍が良いかもしれない。
実装例
乱択ベース、巡回畳み込みと線形性の高速化あり
https://judge.yosupo.jp/submission/211249
参考文献
[1] Clifford, P., & Clifford, R. (2007). Simple deterministic wildcard matching. Information Processing Letters, 101(2), 53-54.
[2] Clifford, R., Efremenko, K., Porat, E., & Rothschild, A. (2009, January). From coding theory to efficient pattern matching. In Proceedings of the twentieth Annual ACM-SIAM Symposium on Discrete Algorithms (pp. 778-784). Society for Industrial and Applied Mathematics.