Saya memiliki masalah pencarian yang cukup rumit yang berhasil saya kurangi menjadi uraian berikut. Saya sudah googling tetapi belum bisa menemukan algoritma yang cocok dengan masalah saya. Khususnya kebutuhan untuk melewatkan bilangan bulat sewenang-wenang. Mungkin seseorang di sini bisa mengarahkan saya ke sesuatu?
Ambil urutan bilangan bulat A, misalnya (1 2 3 4)
Ambil berbagai urutan bilangan bulat dan uji apakah ada yang cocok dengan A sehingga.
- A berisi semua bilangan bulat dalam urutan yang diuji
- Urutan bilangan bulat dalam urutan yang diuji sama dalam A
- Kami tidak peduli tentang bilangan bulat apa pun di A yang tidak dalam urutan pengujian
- Kami ingin semua urutan uji yang cocok, bukan hanya yang pertama.
Sebuah contoh
A = (1 2 3 4)
B = (1 3)
C = (1 3 4)
D = (3 1)
E = (1 2 5)
B cocok dengan A
C cocok A
D tidak cocok dengan A karena pemesanannya berbeda
E tidak cocok dengan A karena mengandung bilangan bulat tidak dalam A
Saya harap penjelasan ini cukup jelas. Yang terbaik yang berhasil saya lakukan adalah membuat pohon dari urutan pengujian dan beralih ke A. Kebutuhan untuk dapat melewati bilangan bulat mengarah ke banyak jalur pencarian yang tidak berhasil.
Terima kasih
Membaca beberapa saran saya merasa saya harus mengklarifikasi beberapa poin yang saya tinggalkan terlalu kabur.
Angka berulang diperbolehkan, pada kenyataannya ini cukup penting karena memungkinkan urutan uji tunggal untuk mencocokkan A adalah beberapa cara
A = (1234356), B = (236), kecocokan bisa berupa -23 --- 6 atau -2--3-6
Saya berharap akan ada jumlah yang sangat besar dari urutan pengujian, dalam ribuan setidaknya dan urutan A akan cenderung memiliki panjang maksimal mungkin 20. Dengan demikian hanya mencoba untuk mencocokkan setiap urutan pengujian satu per satu dengan iterasi menjadi sangat tidak efisien.
Maaf jika ini tidak jelas.
sumber
Jawaban:
Hmm, saya bisa memikirkan dua algoritma yang mungkin: Pemindaian linear melalui urutan A , atau membangun kamus dengan pencarian indeks waktu-konstan.
Jika Anda menguji banyak kemungkinan berikutnya B terhadap urutan A yang lebih besar , saya sarankan Anda menggunakan varian dengan kamus.
Pemindaian Linier
Deskripsi
Kami menjaga kursor untuk urutan A . Kemudian kami mengulangi semua item dalam B berikutnya . Untuk setiap item, kami menggerakkan kursor maju dalam A sampai kami menemukan item yang cocok. Jika tidak ada item yang cocok ditemukan, maka B bukan yang berikutnya.
Ini selalu berjalan di O (seq.size) .
Kodesemu
Gaya imperatif:
Gaya fungsional:
Contoh implementasi (Perl):
Pencarian kamus
Deskripsi
Kami memetakan item dari urutan A ke indeks mereka. Kemudian kami mencari indeks yang sesuai untuk setiap item dalam B , melewati indeks yang kecil, dan memilih indeks sekecil mungkin sebagai batas bawah. Ketika tidak ada indeks yang ditemukan, maka B bukanlah sebuah urutan.
Berjalan dalam sesuatu seperti O (subseq.size · k) , di mana k menjelaskan berapa banyak angka duplikat di dalamnya
seq
. Ditambah overhead O (seq.size)Keuntungan dari solusi ini adalah bahwa keputusan negatif dapat dicapai lebih cepat (turun ke waktu konstan), setelah Anda membayar biaya overhead untuk membangun tabel pencarian.
Kodesemu:
Gaya imperatif:
Gaya fungsional:
Contoh implementasi (Perl):
Varian Pencarian Kamus: Pengkodean sebagai Mesin Status Hingga
Deskripsi
Kami selanjutnya dapat mengurangi kompleksitas algoritme hingga O (subseq.size) jika kami menukar lebih banyak memori. Alih-alih memetakan elemen ke indeks mereka, kami membuat grafik di mana setiap node mewakili elemen di indeksnya. Tepi-tepinya menunjukkan kemungkinan transisi, misalnya urutan
a, b, a
memiliki tepiana@1 → b@2, a@1 → a@3, b@2 → a@3
. Grafik ini setara dengan mesin keadaan terbatas.Selama pencarian, kami mempertahankan kursor yang awalnya merupakan simpul pertama dari pohon. Kami kemudian berjalan tepi untuk setiap elemen dalam sublist B . Jika tidak ada tepi seperti itu, maka B tidak ada sublist. Jika setelah semua elemen kursor berisi simpul yang valid, maka B adalah sublist.
Kodesemu
Gaya imperatif:
Gaya fungsional:
Contoh implementasi (Perl):
sumber
study
kerjanya dan jika algoritma itu berlaku dapat memiliki beberapa aplikasi praktis di sini?study
sebelumnya telah membangun tabel pencarian karakter-ke-posisi, tidak seperti solusi kedua saya.Berikut ini adalah pendekatan praktis yang menghindari "kerja keras" menerapkan algoritma Anda sendiri, dan juga menghindari "menciptakan kembali roda": memanfaatkan mesin ekspresi reguler untuk masalah tersebut.
Masukkan semua angka A ke dalam string, dan semua angka B ke dalam string yang dipisahkan oleh ekspresi reguler
(.*)
. Tambahkan^
karakter di awal dan$
di akhir. Kemudian biarkan mesin ekspresi reguler favorit Anda mencari semua kecocokan. Misalnya kapanA = (1234356), B = (236)
buat reg exp untuk B like
^(.*)2(.*)3(.*)6(.*)$
. Sekarang jalankan pencarian regexp global. Untuk mengetahui posisi mana dalam A yang sesuai dengan Anda, cukup periksa panjang dari 3 kiriman pertama.Jika rentang bilangan bulat Anda meninggalkan 0 hingga 9, Anda dapat mempertimbangkan untuk menyandikannya dengan huruf tunggal terlebih dahulu untuk membuat ini berfungsi, atau Anda harus menyesuaikan ide menggunakan karakter pemisahan.
Tentu saja, kecepatan pendekatan itu akan sangat bergantung pada kecepatan mesin reg exp yang Anda gunakan, tetapi ada mesin yang sangat dioptimalkan yang tersedia, dan saya kira akan sulit untuk menerapkan algoritma yang lebih cepat "di luar kotak" .
sumber
Algoritma ini harus cukup efisien jika mendapatkan panjang dan mengulangi urutannya efisien.
sequence
dan lebih pendeksubsequence
sequence
.sequence
sama dengan angka pada posisi saat inisubsequence
sequence
satu lebih jauhsubsequence
pada akhirsequence
sumber