Apa cara yang ringkas untuk merepresentasikan partisi dari set?

11

Ada struktur data yang efisien untuk mewakili sekumpulan partisi. Struktur data ini memiliki kompleksitas waktu yang baik untuk operasi seperti Union dan Find, tetapi mereka tidak terlalu efisien dalam ruang.

Apa cara hemat-ruang untuk merepresentasikan partisi sekumpulan?

Inilah satu titik awal yang memungkinkan:

Saya tahu bahwa jumlah partisi set dengan elemen adalah , nomor Bell ke- . Jadi kompleksitas ruang optimal untuk merepresentasikan partisi set dengan elemen adalah bits. Untuk menemukan representasi seperti itu, kita bisa mencari pemetaan satu-ke-satu antara (himpunan partisi dari himpunan elemen ) dan (himpunan bilangan bulat dari hingga ).NBNNNlog2(BN)N1BN

Apakah ada pemetaan yang efisien untuk dihitung? Yang saya maksud dengan "efisien" adalah bahwa saya ingin mengubah representasi kompak ini menjadi / dari representasi yang mudah dimanipulasi (seperti daftar daftar) dalam polinomial waktu dalam atau .Nlog2(BN)

cberzan
sumber
bertanya-tanya, seberapa jauh dapat berasal dari pengkodean naif / alami dengan hanya menetapkan bilangan bulat unik ke setiap elemen himpunan tempat bilangan bulat mewakili # partisi? mungkin itu "tidak banyak perbedaan" ...log2(BN)
vzn

Jawaban:

7

Anda dapat menggunakan cara rumus perulangan di bawah ini diperoleh untuk menemukan penyandian Anda: Ini dibuktikan dengan mempertimbangkan berapa banyak elemen lain di bagian yang mengandung elemen . Jika ada di antaranya, maka kita memiliki pilihan , dan pilihan untuk mempartisi sisanya.

Bn+1=k=0n(nk)Bk.
n+1nk(nnk)=(nk)Bk

Dengan menggunakan ini, kita dapat memberikan algoritma rekursif untuk mengubah partisi menjadi angka dalam rentang . Saya berasumsi Anda sudah memiliki cara untuk mengubah subset ukuran dari ke angka dalam rentang (algoritma seperti itu dapat dibuat dengan cara yang sama menggunakan perulangan Pascal ).n+10,,Bn+11k{1,,n}0,,(nk)1(nk)=(n1k)+(n1k1)

Misalkan bagian yang mengandung mengandung elemen lainnya. Temukan kode mereka . Hitung partisi dengan "mengompresi" semua elemen yang tersisa ke rentang itu. Menghitung kode . Kode baru adalahn+1kC1{1,,nk}C2

C=l=0nk1(nl)Bl+C1Bnk+C2.

Di arah lain, diberi kode , temukan unik sehingga dan tentukan Karena , dapat ditulis sebagai , di mana . Sekarang mengkode elemen-elemen di bagian yang berisi , dan mengkode partisi dariCk

l=0nk1(nl)BlC<l=0nk(nl)Bl,
C=Cl=0nk1(nl)Bl.
0C<(nk)BnkC1Bnk+C20C2<BnkC1n+1C2{1,,nk}, yang dapat diterjemahkan secara rekursif. Untuk menyelesaikan decoding, Anda harus "membuka kompresi" partisi terakhir sehingga berisi semua elemen yang tidak muncul di bagian yang berisi .n+1


Berikut adalah cara menggunakan teknik yang sama untuk menyandikan subset dari dengan ukuran , secara rekursif. Jika maka kodenya adalah , jadi anggaplah . Jika maka biarkan menjadi kode , sebagai bagian dari ukuran dari ; kode adalah . Jika maka biarkan menjadi kode , sebagai bagian dari ukuran dari ; kodeS{1,,n}kk=00k>0nSC1S{n}k1{1,,n1}SC1nSC1Sk{1,,n1}Sadalah .C1+(n1k1)

Untuk memecahkan kode , ada dua kasus. Jika kemudian mendekodekan subset dari dengan ukuran yang kodenya , dan menghasilkan . Jika tidak, decode subset dari dengan ukuran yang kodenya adalah , dan output .CC<(n1k1)S{1,,n1}k1CS{n}S{1,,n1}kC(n1k1)S

Yuval Filmus
sumber
Jawaban luar biasa; Terima kasih. Bug kecil: Pada sketsa bukti untuk rumus pengulangan di bagian atas, saya pikir maksud Anda "ada dari itu", bukan "ada dari itu" - maka elemen tersisa dapat dipartisi dengan cara . nkkkBk
cberzan