Tugas Anda adalah untuk memecahkan masalah Sub- urutan Umum Terpanjang untuk n string dengan panjang 1000.
Sebuah solusi yang valid untuk masalah LCS untuk dua atau lebih string S 1 , ... S n adalah string T panjang maksimal sehingga karakter dari T muncul di semua S i , dalam urutan yang sama seperti pada T .
Perhatikan bahwa T tidak harus menjadi sub string dari S i .
Kami telah memecahkan masalah ini dalam jumlah kode terpendek . Kali ini, ukuran tidak masalah.
Contoh
Senar axbycz
dan xaybzc
memiliki 8 urutan umum panjang 3:
abc abz ayc ayz xbc xbz xyc xyz
Semua ini akan menjadi solusi yang valid untuk masalah LCS.
Detail
Tulis program lengkap yang menyelesaikan masalah LCS, seperti dijelaskan di atas, dengan mematuhi aturan berikut:
Input akan terdiri dari dua atau lebih string 1000, yang terdiri dari karakter ASCII dengan titik kode antara 0x30 dan 0x3F.
Anda harus membaca input dari STDIN.
Anda memiliki dua pilihan untuk format input:
Setiap string (termasuk yang terakhir) diikuti oleh linefeed.
String dirantai bersama-sama tanpa pemisah dan tanpa linefeed line.
Jumlah string akan diteruskan sebagai parameter baris perintah ke program Anda.
Anda harus menulis output, yaitu, salah satu solusi yang valid untuk LCS, untuk STDOUT, diikuti oleh satu linefeed.
Bahasa pilihan Anda harus memiliki kompiler / juru bahasa gratis (seperti dalam bir) untuk sistem operasi saya (Fedora 21).
Jika Anda memerlukan flag kompiler atau juru bahasa tertentu, harap sebutkan di posting Anda.
Mencetak gol
Saya akan menjalankan kode Anda dengan string 2, 3, dll. Hingga diperlukan waktu lebih dari 120 detik untuk mencetak solusi yang valid. Ini berarti Anda memiliki 120 detik untuk setiap nilai n .
Jumlah string tertinggi yang menyelesaikan kode dalam waktu adalah skor Anda.
Dalam hal skor n terikat , pengajuan yang memecahkan masalah untuk n string dalam waktu singkat akan dinyatakan sebagai pemenang.
Semua pengiriman akan dihitung waktunya mesin saya (Intel Core i7-3770, 16 GiB RAM, tanpa swap).
The n string dari (n-1) th tes akan dihasilkan dengan menelepon rand n
(dan pengupasan linefeeds, jika diminta), di mana rand
didefinisikan sebagai berikut:
rand()
{
head -c$[500*$1] /dev/zero |
openssl enc -aes-128-ctr -K 0 -iv $1 |
xxd -c500 -ps |
tr 'a-f' ':-?'
}
Kuncinya ada 0
pada kode di atas, tetapi saya berhak untuk mengubahnya ke nilai yang tidak diungkapkan jika saya mencurigai ada orang yang (sebagian) meng-hardcoding output.
sumber
public static void main(...)
?Jawaban:
C, n = 3 dalam ~ 7 detik
Algoritma
Algoritme adalah generalisasi langsung dari solusi pemrograman dinamis standar ke
n
urutan. Untuk 2 stringA
danB
, perulangan standar terlihat seperti ini:Untuk 3 senar
A
,B
,C
saya gunakan:Kode mengimplementasikan logika ini untuk nilai arbitrer dari
n
.Efisiensi
Kompleksitas kode saya adalah O (s ^ n), dengan
s
panjang string. Berdasarkan apa yang saya temukan, sepertinya masalahnya adalah NP-complete. Jadi, sementara algoritma yang diposting sangat tidak efisien untuk nilai yang lebih besarn
, mungkin sebenarnya tidak mungkin dilakukan secara besar-besaran dengan lebih baik. Satu-satunya hal yang saya lihat adalah beberapa pendekatan yang meningkatkan efisiensi untuk huruf kecil. Karena alfabetnya cukup kecil di sini (16), itu bisa mengarah pada peningkatan. Saya masih memprediksi bahwa tidak ada yang akan menemukan solusi yang sah yang lebih tinggi daripadan = 4
dalam 2 menit, dann = 4
sudah terlihat ambisius.Saya mengurangi penggunaan memori dalam implementasi awal, sehingga bisa menangani
n = 4
waktu yang cukup. Tapi itu hanya menghasilkan panjang urutan, bukan urutan itu sendiri. Periksa riwayat revisi posting ini untuk melihat kode itu.Kode
Karena loop lebih dari matriks n-dimensi membutuhkan lebih banyak logika daripada loop tetap, saya menggunakan loop tetap untuk dimensi terendah, dan hanya menggunakan logika looping umum untuk dimensi yang tersisa.
Instruksi untuk Berlari
Untuk berlari:
lcs.c
.Kompilasi dengan opsi optimasi tinggi. Saya menggunakan:
Di Linux, saya akan mencoba:
Jalankan dengan 2 hingga 4 urutan yang diberikan sebagai argumen baris perintah:
Kutip tunggal argumen baris perintah jika perlu, karena alfabet yang digunakan untuk contoh berisi karakter khusus shell.
Hasil
test2.sh
dantest3.sh
merupakan urutan uji dari Dennis. Saya tidak tahu hasil yang benar, tetapi hasilnya terlihat setidaknya masuk akal.sumber
N_MAX
sebagai makro dan menambahkan flag kompiler-std=c99
untuk mengkompilasi kode Anda dengan GCC.Jawaban ini saat ini rusak karena bug. Memperbaiki segera ...
C, 2 string dalam ~ 35 detikIni sangat banyak pekerjaan yang sedang berlangsung (seperti yang ditunjukkan oleh kekacauan yang mengerikan), tetapi mudah-mudahan itu memicu beberapa jawaban yang bagus!
Kode:
Fungsi yang relevan yang melakukan semua perhitungan LCS adalah fungsi
LCS
. Kode di atas akan mengatur waktu panggilannya sendiri ke fungsi ini.Simpan sebagai
main.c
dan kompilasi dengan:gcc -Ofast main.c -o FLCS
Kode dapat dijalankan dengan argumen baris perintah atau melalui stdin. Saat menggunakan stdin, ia mengharapkan sejumlah string diikuti oleh string itu sendiri.
Atau:
Pada kotak Mac OS X dengan 1.7Ghz Intel Core i7 dan test case yang disediakan Dennis, kami mendapatkan output berikut untuk 2 string:
Pendekatannya sangat mirip dengan pendekatan saya dengan tantangan sebelumnya, di sini . Selain pengoptimalan sebelumnya, kami sekarang memeriksa jumlah total karakter yang dibagi antara string di setiap rekursi dan keluar lebih awal jika tidak ada cara untuk mendapatkan substring yang lebih lama daripada yang sudah ada.
Untuk saat ini, ia menangani 2 string, tetapi cenderung mengalami crash-y pada lebih banyak. Lebih banyak peningkatan dan penjelasan yang lebih baik untuk datang!
sumber