Saya membaca makalah NJ Larsson, A. Moffat: Offline Dictionary-Based Compression , yang menjelaskan algoritma kompresi yang, jika saya memahaminya dengan benar, sangat mirip dengan pengkodean pasangan byte .
Diberikan string dengan panjang , saya mencoba memahami bagaimana seseorang dapat memampatkannya dalam linear, , waktu dengan metode kompresi ini. Bagaimana tepatnya hal ini dilakukan? Saya sudah membaca makalah, tetapi saya masih tidak mengerti bagaimana mereka mencapai waktu linier, jadi mungkin saya akan memahaminya menjelaskan dengan cara yang berbeda.
Kebingungan pertama saya muncul pada langkah pertama dalam algoritma, di mana kami menemukan pasangan yang paling umum, misalnya dalam abcababcabc
pasangan yang paling umum ab
akan digantikan oleh simbol baru, katakanlah XcXXcXc
. Saya tidak mengerti bagaimana kita dapat menemukan pasangan yang paling umum dengan cukup cepat. Pendekatan naif saya adalah melihat pertama pada pasangan pertama ab
dan kemudian menghitung jumlah kemunculan, kemudian melihat pasangan berikutnya bc
dan menghitung jumlah kemunculan, dll. Namun ini sudah memberikan hanya untuk menemukan pasangan paling umum satu kali .
Selanjutnya, bahkan jika saya mengerti bagaimana menemukan pasangan paling umum dalam waktu . Masalah saya berikutnya adalah, bukankah kita harus menemukan pasangan paling umum hingga kali? Dan karenanya ini akan memberikan total waktu ?
Jawaban:
Saya telah memeriksa kodenya, membaca ulang makalahnya dan sepertinya algoritma tidak berkinerja dalam seperti yang Anda gambarkan. Panggilan rekursif untuk menemukan pasangan berfungsi diO(n)
O(nlogn) dibagi dengan konstanta jika Anda ingin mengemasnya sampai akhir. Bahkan struktur di bawahnya membuat pointer ke kejadian pertama dari pasangan, membagi antrian pasangan dengan kejadian untuk membuatnya efisien, tetapi tetap loglinear. Di sisi lain dengan menganalisis kode yang ditulis oleh Ph.D. mahasiswa penulis, saya telah menemukan beberapa trik - panjang pasangan (nama asli) diberikan sebagai parameter (standarnya adalah 2) dan pengulangan dibatasi oleh parameter, yang dapat membuang panggilan lebih lanjut (standarnya adalah sekitar 5 level), dengan kemampuan untuk membuat hanya satu operan atau dorong ke ujung. Kode default berjalan di , tetapi tidak akan menghasilkan kompresi optimal. Ada juga yang beralih memilih memori, waktu atau netral.O(n)
Makalah dan kode menunjukkan penggunaan tabel hash, yang berjalan hanya dalam waktu konstan yang diharapkan, tetapi fungsi yang diberikan bekerja sangat baik dengan karakter. Juga kode membatasi panjang input oleh hardcode konstan.
Mengubah hashtable untuk suffix tree dan mengubah bagian perulangan menjadi pembukuan berpasangan akan menghasilkan hasil yang lebih baik - Saya tidak yakin apakah ini mungkin untuk membuatnya , ini mungkin pertanyaan yang berbeda.O(n)
Ada juga trik yang digunakan untuk menjaga ruang kosong dari melintasi - awal blok kosong menunjuk ke karakter non-kosong pertama, tetapi ini hanya mempercepat melintasi, masih dengan waktu loglinear. Bagian yang bertanggung jawab untuk perilaku ini adalah mengganti pasangan dengan karakter baru setiap iterasi - menjaga hanya aturan penulisan ulang dan mengoperasikannya akan lebih cepat, tetapi masih akses untuk memeriksa apakah pasangan baru diperkenalkan akan perlu memeriksa aturan penulisan ulang terhadap yang baru - dalam kasus ini kita membangun pohon biner penuh dengan pasangan di daun sedemikian rupa sehingga setelah mengganti pasangan dengan karakter baru dan menyimpulkan dengan induk kita mendapatkan pasangan baru di daun hingga ke akar - ada karakter lalu berpasangan, lalu ,n n2 n4 n8 , ... Anda melihat polanya, ada pasangan, tetapi menurut deskripsi algoritma ini yelds waktu hanya input lintasan.n16 2n O(nlogn+n)
sumber