OK, jadi saya tidak terdengar seperti orang bodoh. Saya akan menyatakan masalah / persyaratan secara lebih eksplisit:
- Jarum (pola) dan tumpukan jerami (teks untuk dicari) keduanya adalah string C-style null-dihentikan. Tidak ada informasi panjang disediakan; jika perlu, itu harus dihitung.
- Fungsi harus mengembalikan pointer ke kecocokan pertama, atau
NULL
jika tidak ada kecocokan yang ditemukan. - Kasus kegagalan tidak diperbolehkan. Ini berarti setiap algoritma dengan persyaratan penyimpanan non-konstan (atau besar konstan) akan perlu memiliki kasus mundur untuk kegagalan alokasi (dan kinerja dalam perawatan mundur dengan demikian berkontribusi terhadap kinerja kasus terburuk).
- Implementasinya harus dalam C, meskipun deskripsi yang baik dari algoritma (atau tautan ke sana) tanpa kode juga baik-baik saja.
... dan juga yang saya maksud dengan "tercepat":
- Deterministik di
O(n)
manan
= panjang tumpukan jerami. (Tetapi dimungkinkan untuk menggunakan ide-ide dari algoritma yang biasanyaO(nm)
(misalnya rolling hash) jika mereka dikombinasikan dengan algoritma yang lebih kuat untuk memberikan deterministikO(n)
hasil ). - Tidak pernah melakukan (terukur; beberapa jam untuk
if (!needle[1])
dll. Lebih baik) lebih buruk daripada algoritma brute force naif, terutama pada jarum yang sangat pendek yang kemungkinan merupakan kasus yang paling umum. (Overhead preprocessing berat tanpa syarat adalah buruk, seperti sedang mencoba untuk meningkatkan koefisien linear untuk jarum patologis dengan mengorbankan kemungkinan jarum.) - Diberikan jarum dan tumpukan jerami yang sewenang-wenang, kinerja yang sebanding atau lebih baik (tidak lebih buruk dari 50% waktu pencarian lebih lama) dibandingkan dengan algoritma lain yang banyak diimplementasikan.
- Selain dari kondisi ini, saya meninggalkan definisi "tercepat" terbuka. Jawaban yang bagus harus menjelaskan mengapa Anda menganggap pendekatan yang Anda sarankan "tercepat".
Implementasi saya saat ini berjalan kira-kira antara 10% lebih lambat dan 8 kali lebih cepat (tergantung pada input) daripada implementasi Two-Way glibc.
Pembaruan: Algoritma optimal saya saat ini adalah sebagai berikut:
- Untuk jarum dengan panjang 1, gunakan
strchr
. - Untuk jarum dengan panjang 2-4, gunakan kata-kata mesin untuk membandingkan 2-4 byte sekaligus sebagai berikut: Preload jarum dalam bilangan bulat 16 atau 32-bit dengan bithifts dan daur keluar byte lama / byte baru dari tumpukan jerami di setiap iterasi . Setiap byte tumpukan jerami dibaca tepat sekali dan menimbulkan cek terhadap 0 (akhir string) dan satu perbandingan 16 atau 32-bit.
- Untuk jarum dengan panjang> 4, gunakan algoritma Two-Way dengan tabel shift yang buruk (seperti Boyer-Moore) yang hanya diterapkan pada byte terakhir dari jendela. Untuk menghindari overhead menginisialisasi tabel 1kb, yang akan menjadi kerugian bersih untuk banyak jarum dengan panjang sedang, saya menyimpan array bit (32 byte) yang menandai entri mana dalam tabel shift yang diinisialisasi. Bit yang tidak disetel berhubungan dengan nilai byte yang tidak pernah muncul di jarum, yang memungkinkan pergeseran panjang jarum penuh.
Pertanyaan besar yang tersisa di pikiran saya adalah:
- Apakah ada cara untuk memanfaatkan tabel shift yang buruk dengan lebih baik? Boyer-Moore memanfaatkannya dengan memindai ke belakang (kanan-ke-kiri), tetapi Two-Way membutuhkan pemindaian kiri-ke-kanan.
- Hanya dua algoritma kandidat yang layak yang saya temukan untuk kasus umum (tidak ada kehabisan memori atau kondisi kinerja kuadratik) adalah Two-Way dan String Matching pada Alphabets yang Dipesan . Tetapi apakah ada kasus yang mudah terdeteksi di mana algoritma yang berbeda akan optimal? Tentu saja banyak
O(m)
(di manam
panjang jarum) dalam algoritma ruang dapat digunakan untukm<100
atau lebih. Mungkin juga untuk menggunakan algoritma yang kuadratik terburuk jika ada tes mudah untuk jarum yang terbukti hanya membutuhkan waktu linier.
Poin bonus untuk:
- Dapatkah Anda meningkatkan kinerja dengan mengasumsikan bahwa jarum dan tumpukan jerami adalah UTF-8 yang baik? (Dengan karakter dengan panjang byte yang berbeda-beda, well-formed-ness memaksakan beberapa persyaratan penyelarasan string antara jarum dan tumpukan jerami dan memungkinkan perpindahan 2-4 byte secara otomatis ketika byte head yang tidak cocok ditemukan. Tetapi apakah kendala ini membuat Anda banyak / apa pun di luar apa yang perhitungan sufiks maksimal, pergeseran sufiks yang baik, dll. sudah memberi Anda berbagai algoritma?)
Catatan: Saya menyadari sebagian besar algoritma di luar sana, hanya saja tidak sebagus apa yang mereka lakukan dalam praktik. Berikut ini adalah referensi yang baik sehingga orang tidak terus memberi saya referensi tentang algoritma sebagai komentar / jawaban: http://www-igm.univ-mlv.fr/~lecroq/string/index.html
strstr
sebagai sesuatu untuk nanti, jadi saya belum benar-benar sempat membaca dengan baik kertas yang Anda tautkan, tetapi kedengarannya sangat menjanjikan. Terima kasih dan maaf karena tidak membalas Anda.