Tamam, bu yüzden bir aptal gibi gelmiyor, problemi / gereksinimleri daha açık bir şekilde ifade edeceğim:
- İğne (desen) ve samanlık (aranacak metin) C tarzı boş sonlandırılmış dizelerdir. Uzunluk bilgisi verilmez; gerekirse hesaplanmalıdır.
- İşlev ilk eşleşmeye veya
NULL
eşleşme bulunmazsa bir işaretçi döndürmelidir . - Arıza durumlarına izin verilmez. Bu, sabit olmayan (veya büyük sabit) depolama gereksinimlerine sahip herhangi bir algoritmanın, ayırma hatası için bir geri dönüş durumuna sahip olması gerektiği anlamına gelir (ve geri dönüş bakımındaki performans, en kötü durum performansına katkıda bulunur).
- Kod olmadan algoritmanın iyi bir açıklaması (veya buna bağlantı) iyi olsa da uygulama C'de olmalıdır.
... yanı sıra "en hızlı" ile kastettiğim:
- Deterministik
O(n)
nereden
= samanlık uzunluğu. (AncakO(nm)
, deterministikO(n)
sonuçlar vermek için daha sağlam bir algoritma ile birleştirilirlerse , normal olan algoritmalardan (örneğin, yuvarlama karma) fikirleri kullanmak mümkün olabilir ). - Asla
if (!needle[1])
naif kaba kuvvet algoritmasından, özellikle de en sık görülen durum olan çok kısa iğnelerde asla (ölçülebilir bir şekilde, birkaç saat, vb. İçin uygundur) iyi performans göstermez. (Koşulsuz ağır önişleme yükü, olası iğneler pahasına patolojik iğneler için doğrusal katsayıyı iyileştirmeye çalıştığı için kötüdür.) - Yaygın olarak uygulanan diğer algoritmalara göre rastgele bir iğne ve samanlık göz önüne alındığında, karşılaştırılabilir veya daha iyi performans (% 50 daha uzun arama süresinden daha kötü değil).
- Bu koşulların yanı sıra, "en hızlı" açık uçlu tanımını bırakıyorum. İyi bir yanıt, önerdiğiniz yaklaşımı neden "en hızlı" olarak değerlendirdiğinizi açıklamalıdır.
Mevcut uygulamam, glibc'nin İki Yönlü uygulamasından yaklaşık% 10 daha yavaş ve 8 kat daha hızlı (girdiye bağlı olarak) çalışıyor.
Güncelleme: Mevcut optimal algoritmam aşağıdaki gibidir:
- 1 uzunluktaki iğneler için kullanın
strchr
. - Uzunluğu 2-4 olan iğneler için, bir kerede 2-4 baytı karşılaştırmak için makine kelimelerini kullanın: İğneyi bit kaydırmalarla 16 veya 32 bit tamsayıya önceden yükleyin ve her bir yinelemede samanlıktan eski bayt çıkışını / yeni baytları döndürün . Samanlıktaki her bayt tam olarak bir kez okunur ve 0 (dizginin sonu) ve bir 16- veya 32-bit karşılaştırması için bir kontrol yapar.
- Uzunluk> 4 olan iğneler için, yalnızca pencerenin son baytına uygulanan kötü bir kaydırma tablosu (Boyer-Moore gibi) olan İki Yönlü algoritma kullanın. Birçok orta uzunlukta iğne için net bir kayıp olacak bir 1kb tablo başlatmanın yükünü önlemek için, shift tablosundaki hangi girişlerin başlatıldığını işaretleyen bir bit dizisi (32 bayt) tutarım. Ayarlanmamış bitler, iğne içinde hiç görünmeyen, tam iğne uzunluğu kaydırmanın mümkün olduğu bayt değerlerine karşılık gelir.
Aklımda kalan büyük sorular:
- Kötü vardiya tablosundan daha iyi yararlanmanın bir yolu var mı? Boyer-Moore en iyi şekilde geriye doğru (sağdan sola) tarayarak kullanır, ancak İki Yönlü bir soldan sağa tarama gerektirir.
- Genel durum için bulduğum tek iki uygulanabilir aday algoritması (bellek yetersiz veya karesel performans koşulları yok) Sıralı Alfabelerde İki Yönlü ve Dizeli Eşleştirme . Ancak, farklı algoritmaların en uygun olacağı, kolayca tespit edilebilen durumlar var mı? Uzay algoritmalarındaki
O(m)
(m
iğne uzunluğunun nerede olduğu) kesinlikle bir kısmı için kullanılabilirm<100
. Ayrıca, sadece doğrusal zaman gerektiren iğneler için kolay bir test varsa, en kötü durumda ikinci dereceden algoritmalar kullanmak da mümkün olacaktır.
Bonus puanları:
- Hem iğne hem de samanlığın iyi oluşturulmuş UTF-8 olduğunu varsayarak performansı artırabilir misiniz? (Değişen bayt uzunluklarındaki karakterlerde, iyi biçimlendirilmiş iğne, iğne ve samanlık arasında bazı dize hizalama gereksinimleri uygular ve uyuşmayan bir kafa baytıyla karşılaşıldığında otomatik 2-4 bayt kaydırmaya izin verir. Ancak bu kısıtlamalar size, maksimum ek hesaplamaları, iyi son ek kaymaları vb. size çeşitli algoritmalar veriyor mu?)
Not: Orada algoritmaların çoğunun iyi farkındayım, pratikte ne kadar iyi performans gösterdiklerini değil. İşte iyi bir referans, böylece insanlar bana algoritmalar hakkında yorum / cevap olarak referans vermiyorlar: http://www-igm.univ-mlv.fr/~lecroq/string/index.html
strstr
sonra için bir şey olarak daha fazla gelişme bıraktım , bu yüzden bağladığınız kağıdı düzgün bir şekilde okumak için etrafta dolaşmadım, ancak kulağa çok umut verici geliyor. Sana geri dönmediğin için teşekkürler ve üzgünüm.