2010-07-31 45 views
8

Bu article, geri izlemede O (2^n) olan bir düzenli ifadenin olduğunu gösterir. Örnek, (x+x+)+y. xxxx ... p gibi bir dizeyle eşleşmeye çalışıldığında, eşleşemediğinden önce bir süre geriye doğru gidecektir.Bir regexp ifadesinin üstel olduğunu tespit edin

Böyle bir regexp'i algılamanın bir yolu var mı?

sayesinde

cevap

8

sizin regexp'in motoru için çalışma zamanı üstel davranış ortaya ederse (x + x +) + y, o zaman bir DFA NFA bu doğrusal zamanda desen tanıyabilir çünkü kırık olduğunu . (A geribaşvuru ile regexp'in değil artık dil teorik anlamda bir düzenli ifade olması nedeniyle, ağırlıklı olarak)

Aslında, geri adım gerçekten ihtiyaç vardır (geribaşvuruların gibi) sadece birkaç durum vardır. Yetenekli bir uygulama, yalnızca bu köşe durumları verildiğinde geri dönüşe geçmelidir.

Dürüstlükte, DFA'lar da karanlık bir yüzeye sahiptir, çünkü bazı regexp'ler üstel boyut gereksinimlerine sahiptir, ancak boyut kısıtlamalarından daha büyük boyuttaki bir DFA'nın uygulanması daha kolaydır ve büyük DFA, girişte doğrusal olarak çalışır; X'in bir çiftinde boğucu küçük bir backtracker.

You should gerçekten regexp'nin uygulanması (ve geriye dönüş patolojik davranışı) hakkında Russ Cox mükemmel bir makale serisi okuyun: http://swtch.com/~rsc/regexp/

karar verilebilirlik ile ilgili sorunuza gelince: Yapamazsın. Çünkü regexpr için numaralı geri izleme yok. Her uygulamanın, belirli durumlarda algoritmalarında üstel büyüme ile başa çıkmak için kendi stratejileri vardır ve başkalarını kapsamaz. Bir kural buraya uygun ve orada felaket olabilir.

GÜNCELLEME:

Örneğin, bir uygulama onları çalıştırmadan önce İfadelerinin basitleştirmek için cebirsel dönüşümleri kullanabilirsiniz bir iyimserlik içerebilir: (x+x+)+y herhangi backtracker için bir sorun olmamalı, aynı bir xxx*y vardır.Ancak aynı optimizatör bir sonraki ifadeyi tanıyamaz ve problem yine oradadır. Orada birçok regex motorları gerçek dünyada bu şekilde yapmasalar da,

http://perlgeek.de/blog-en/perl-tips/in-search-of-an-exponetial-regexp.html

2

No ben öyle düşünmüyorum, ancak bu yönergeleri kullanabilirsiniz: açık uçlu yüksek ucunda olan iki nicelik içeriyorsa

  • ve onlar o zaman iç içe olan , O (2^n) olabilir.
  • Bu tür iki niceleyici içermiyorsa, o zaman O (2^n) olamayacağını düşünüyorum. Bu neden olabilir

Niceleyiciler şunlardır: *, + ve {k,}. Ayrıca, düzenli bir ifadeyi değerlendirmenin en kötü durum karmaşıklığının, tipik dizelerdeki karmaşıklıktan çok farklı olabileceğini ve karmaşıklığın belirli normal ifade motoruna bağlı olabileceğini de unutmayın. ikisi de hemen cevap

echo "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" | egrep "(x+x+)+y" 
echo "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxy" | egrep "(x+x+)+y" 

:

+0

Yeap ama siz "O (2^n) olabilir" dediniz emin olmak için bir yol var mı? Regexp dönüştürmek gibi bir yol var mı bu şekilde üstel değil gösterilebilir? – mathk

1

geribaşvuruların olmadan herhangi regex doğrusal zamanda eşleştirilebilir: Burada birileri Perl'in optimize edici aptallar bir RegExpr zanaat nasıl tarif (programlama dili çalışma ortamı ortamlarına bağlanan en az sayıda regex motoru, geri dönüşleri destekler ve herhangi bir geri bildirim olmadığında daha verimli bir yürütme modeline geçmez).

Geridönüşümlü düzenli ifadelerin ne kadar zaman harcayacağını öğrenmenin kolay bir yolu yoktur.

1

İç içe tekrarları, star height 1'e karşılık gelen bir regex çözümleyici kullanarak algılayabilir ve reddedebilirsiniz.npm'den bir regex çözümleyici kullanarak yazdım.

$ node safe.js '(x+x+)+y' 
false 
$ node safe.js '(beep|boop)*' 
true 
$ node safe.js '(a+){10}' 
false 
$ node safe.js '\blocation\s*:[^:\n]+\b(Oakland|San Francisco)\b' 
true 
+1

üstel regexp'in 1 yıldız yüksekliği vardır, ancak 1 yıldızın tüm yıldız yüksekliğinin üstel olması gerekmez. Örneğin alırsanız: '(a | b) * a' – mathk

İlgili konular