キーがregexである要素の配列があります。指定された文字列 ( regexではない) が、キーregexの実行に基づいて一致する配列値をO(N)時間未満で返す高速アルゴリズムを考え出したいと思います。
現在、配列の線形スキャンを行っています。要素ごとに、posix regexec API を使用してそれぞれの正規表現を実行していますが、これは、一致する要素を見つけるために、配列全体を検索する必要があることを意味します。
配列がキーとして単純な文字列のみで構成されている場合、配列を保持してbsearchスタイルの APIを使用することもできましたが、正規表現ではそれほど簡単ではないようです。
ここで何か不足していますか?
例は次のとおりです
// this is mainly to be considered
// as pseudocode
typedef struct {
regex_t r;
... some other data
} value;
const char *key = "some/key";
value my_array[1024];
bool my_matches[1024];
for(int i =0; i < 1024; ++i) {
if(!regexec(&my_array[i].r, key, 0, 0, REG_EXTENDED))
my_matches[i] = 1;
else
my_matches[i] = 0;
}
しかし、ご覧のとおり、上記は線形です。ありがとう
補遺:
上記のアルゴリズムと以下の回答で提案されているものを実行する単純な実行可能ファイルをまとめました。ここでは、大きな正規表現からサブ正規表現のバイナリツリーを構築し、それをナビゲートしてすべての一致を見つけます。
ソースコードはこちら (GPLv3): http://qpsnr.youlink.org/data/regex_search.cpp
コンパイル:g++ -O3 -o regex_search ./regex_search.cpp -lrt
および実行: ./regex_search "a/b"
(または--help
オプションのフラグを使用)
興味深いことに (予想通りだと思いますが)、ツリー内を検索する場合、実行に必要な正規表現の数は少なくて済みますが、これらは比較ごとに実行するのがはるかに複雑であるため、最終的にかかる時間はベクトルの線形スキャンと釣り合いがとれます. 結果が印刷されてstd::cerr
いるので、それらが同じであることがわかります。
長い文字列や多くのトークンを使用して実行する場合は、メモリの使用量に注意してください。Ctrl-C
システムがクラッシュするのを防ぐために、ヒットする準備をしてください。