昨日のStackOverflowの停止に続いて-正規表現のマッチングは本当に難しいですか、それとも実装は単に非効率的ですか?


8

昨日、StackOverflowが30分ダウンしました。その後、彼らはそれについてブログの投稿を書き、問題が正規表現マッチングの予想外に高い複雑さから生じたことを詳述しました。

つまり、正規表現a+bは、文字列aaaaaaaaaaaaaacで実行される場合、バックトラックを使用するため、時間で実行されますは文字数です。O2a

次のPythonコードで問題を再現できます。私のコンピューターでは、実行に4秒以上かかります。

import re, time
start = time.time()
re.findall(r'\s+$', ' '*20000 + 'x')
print(time.time() - start)

これは私にとって非常に驚きました。私が考えたのだろう必要があるだろうこれ、正規表現からDFAを構築し、それを通じて、希望の文字列を実行することにより、例えば、正規表現マッチャがより効率的に動作することを考えていると思います(DFA工事は含みません)。O

(たとえば、Cormen、Leiserson、Rivestによる本のアルゴリズムの紹介は、Knuth-Morris-Prattアルゴリズムを導入する方法について同様のアルゴリズムを通過します)。

私の質問:アルゴリズムを許可しない正規表現マッチングに本質的に難しいものはありますかO、または単に非効率的な実装(Pythonで、StackOverflowが使用するものなど)について話しているだけですか?


2
これについての記事があります。ここにあると思いますが、執筆時点ではサーバーはダウンしています。エグゼクティブサマリーは、はい、ここで問題の原因となったようなリテラル正規表現を実行しているだけであれば、オートマトンにコンパイルすることで線形時間で照合できますが、インタープリター型言語の場合、時間を考慮する必要があります。コンパイルには時間がかかりますし、それを行う価値があるかどうかです。
David Richerby 16

この正規表現を書き換えて高速化できますか?私は本当にsubstr関数に行く必要があるということですか、それとも彼はより良い正規表現を考えることができますか?これについて正確に話しています/ \ s + $ / on( "" * 20000)+ "x"
Nakilon

回答:


8

正規表現のみを解析したい場合は、そのような問題はありません(本当に無能なプログラマでなければ)。警告には、オートマトンを構築するために必要な時間が含まれます。漸近的に悪いアルゴリズムは、実際には多くの場合オートマトンのアプローチよりも優れているかもしれません。

本当の問題は、彼らがライブラリ関数を使用することはおそらくであるとの契約正規表現されている方法で、より強力な無地の正規表現より。また、グループのマッチングなどの機能により、さらに複雑になります。

この場合、これらのエンジンは部分文字列に一致し(プレーンな正規表現では通常、入力全体のみに一致します)、バックトラックを使用するため、問題が発生しました。最終的に不一致になる長い部分一致は、長いバックトラックを引き起こします。本質的に、これはナイーブな2次時間の文字列照合の最悪のケースです。

これを改善できますか?多分。文字列照合オートマトンのアイデアを使用して、2番目のシンボルではなく、パターンのプレフィックスと一致する最も長いサフィックスの先頭に戻ります。しかし、パターンはもはや固定されていないので、アイデアを拡張することは確かに簡単ではありません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.