algoritma untuk masalah paritas awalan

8

Masalah paritas awalan dapat didefinisikan sebagai berikut. Anda diberi string dengan panjang dan pada awalnya setiap karakter adalah . Maka Anda ingin membangun struktur data yang dapat mendukung pembaruan seperti berikut ini.Sn0

  1. Untuk yang diberikan mengubah menjadi atauiS[i]01
  2. untuk diberikan menemukan paritas .iS[1]+S[2]+...+S[i]

Dari atas kepala saya, ada solusi yang dapat mendukung jenis pertanyaan ini dalam waktu , sementara hanya menggunakan ruang linear dan waktu praproses linear untuk membangun struktur data. Idenya adalah untuk membangun pohon pencarian biner lengkap di atas string di mana daun sesuai dengan karakter individu dan di setiap simpul internal kita menyimpan jumlah semua karakter yang merupakan daun di sub pohon yang ditentukan oleh simpul itu. Dengan cara ini, kami dapat dengan mudah mendukung kedua pembaruan dalam waktu .O(logn)SO(logn)

Namun, saya menemukan makalah yang membuktikan batas bawah untuk masalah ini, menyatakan bahwa Anda tidak dapat melakukan lebih baik daripada untuk pembaruan, dan saya juga menemukan kertas berikut http://link.springer.com/chapter/10.1007%2F3-540-51542-9_5 , dan tautan langsung ke pdf , memberikan algoritme yang mencapai batas itu, sehingga menjadi optimal.O(lognloglogn)

Saya ingin memahami algoritme ini namun penjelasannya seperti 1 halaman, dan banyak detail yang hilang.

Jadi saya bertanya-tanya apakah ada sumber lain pada masalah ini, karena saya merasa sangat sulit untuk menemukan, atau apakah ini satu-satunya sumber yang tersedia?

Terima kasih sebelumnya

jsguy
sumber

Jawaban:

9

Saya membaca cepat kertas yang Anda tautkan. Berdasarkan ide yang diberikan dalam makalah itu, berikut adalah struktur data sederhana yang memperolehO(lognloglogn) terikat waktu pada setiap operasi.

Anda menyebutkan dalam pertanyaan Anda bahwa Anda dapat menggunakan pohon yang seimbang dan ditambah untuk mempercepat ini. Secara khusus, jika Anda memiliki pohon biner dan menambah setiap node dengan paritas subtree kirinya, maka Anda dapat melakukan pembaruan dan pencarian dalam waktuO(logn)setiap. Itu cepat, tetapi tidak cukup cepat.

Sekarang, pertimbangkan generalisasi ide Anda berikut ini. Misalkan alih-alih menggunakan pohon biner, kami menggunakan pohon multiway dengan faktor percabangank. Kami menambah setiap kunci di setiap node dengan paritas dari semua subtree yang mendahuluinya (ini menggeneralisasi ide untuk menyimpan paritas subtree kiri). Sekarang, mari kita pikirkan tentang bagaimana kita melakukan pencarian atau pembaruan di pohon ini. Untuk melakukan pencarian, kami menggunakan versi yang sedikit dimodifikasi dari algoritma pencarian pohon biner dari sebelumnya: berjalan dari atas pohon ke bawah, pada setiap langkah mengumpulkan paritas subtree murni di sebelah kiri setiap node. Ketinggian pohon dalam hal ini akan menjadiHAI(catatankn) dan kami lakukan HAI(1) bekerja per node, jadi biaya melakukan pencarian akan HAI(catatankn).

Namun, dengan pengaturan ini, biaya melakukan pembaruan meningkat. Secara khusus, jika kita mengubah paritas elemen, kita perlu berjalan dari bawah pohon ke atas, mengubah paritas yang disimpan dari setiap kunci di setiap node di jalan menuju ke atas. Adak kunci per node dan HAI(catatankn) node pada jalur ke atas dari daun, sehingga biaya melakukan operasi seperti ini akan menjadi HAI(kcatatankn)=HAI(kcatatankcatatann), yang terlalu lambat. Jika kita entah bagaimana bisa menghilangkan ini ekstrak istilahnya, maka kita akan berada dalam bisnis.

Wawasan yang dimiliki makalah ini adalah sebagai berikut. Jika Anda memikirkan masalah awal kami, kami memiliki berbagai ukuranndan ingin dapat menghitung paritas awalan. Kami sekarang memilikik-ary tree di mana, di setiap node, kita harus mampu menyelesaikan masalah paritas awalan pada array ukuran kmasing-masing, karena setiap simpul menyimpan informasi tentang lapisan di bawahnya. Dalam struktur data di atas, kami memecahkan masalah paritas awalan di setiap node dengan hanya menyimpan array paritas awalan, yang berarti bahwa jika kita perlu melakukan pembaruan, biayanya adalahHAI(k). Wawasan makalah ini adalah bahwa dengan menggunakan struktur data yang lebih pintar di setiap node, Anda dapat melakukan pembaruan ini secara signifikan lebih efisien.

Secara khusus, makalah ini membuat wawasan berikut. Mari kita anggap itukadalah "kecil," untuk beberapa definisi kecil yang akan kami pilih nanti. Jika Anda ingin menyelesaikan masalah paritas awalan pada berbagai ukurank, maka hanya ada 2k mungkin sedikit berbeda panjang array k. Selain itu, hanya adak kemungkinan permintaan pencarian yang bisa Anda buat pada bit array ukuran k. Akibatnya, jumlah kemungkinan kombinasi array dan kueri adalahk2k. Jika kita memilihkuntuk menjadi cukup kecil, kita dapat membuat jumlah ini sangat kecil sehingga menjadi layak untuk melakukan prakiraan hasil dari setiap kemungkinan array dan setiap kemungkinan query. Jika kami melakukan itu, maka kami dapat memperbarui struktur data kami sebagai berikut. Di setiap nodekpohon jalan, daripada memiliki setiap kunci menyimpan paritas subtree kirinya, kami malah menyimpan array kbit, satu untuk setiap kunci di simpul. Ketika kita ingin menemukan paritas semua node di sebelah kirisayath anak, kita hanya melakukan pencarian di tabel yang diindeks oleh mereka k bit (diperlakukan sebagai bilangan bulat) dan indeks saya. Asalkan kita dapat menghitung tabel ini dengan cukup cepat, ini berarti melakukan permintaan paritas awalan masih akan memakan waktuHAI(catatankn), tetapi sekarang pembaruan membutuhkan waktu HAI(catatankn) juga karena biaya permintaan paritas awalan pada node yang diberikan akan HAI(1).

Para penulis makalah memperhatikan bahwa jika Anda memilih k=lgn2, maka jumlah kueri yang mungkin bisa dibuat adalah lgn22lgn2=lgn2n=Hai(n). Selain itu, biaya untuk melakukan operasi apa pun pada pohon yang dihasilkan akan menjadiHAI(catatankn)=HAI(catatanncatatanlgn2)=HAI(catatanncatatancatatann). Tangkapannya adalah yang sekarang perlu Anda lakukanHai(n)precomputation pada awal pengaturan struktur data. Para penulis memberikan cara untuk mengamortisasi biaya ini dengan menggunakan struktur data yang berbeda untuk permintaan awal sampai cukup banyak pekerjaan yang telah dilakukan untuk membenarkan melakukan pekerjaan yang diperlukan untuk mengatur tabel, meskipun Anda bisa berpendapat bahwa Anda perlu menghabiskanHAI(n) waktu membangun pohon di tempat pertama dan bahwa ini tidak akan mempengaruhi runtime keseluruhan.

Jadi, secara ringkas, idenya adalah sebagai berikut:

  • Alih-alih menggunakan pohon biner yang ditambah, gunakan yang ditambah kpohon -ary.
  • Perhatikan itu dengan kecil k, semuanya mungkin kdaftar-bit dan permintaan pada daftar tersebut dapat dihitung sebelumnya.
  • Gunakan struktur data yang dikomputasi ini di setiap node di pohon.
  • Memilih k=lgn2 untuk membuat pohon tinggi, dan, karenanya, biaya per operasi, HAI(catatanncatatancatatann).
  • Hindari biaya precomputation dimuka dengan menggunakan struktur data penggantian sementara di setiap node sampai precomputation menjadi berharga.

Secara keseluruhan, ini adalah struktur data yang pintar. Terima kasih telah mengajukan pertanyaan ini dan menautkannya - saya belajar banyak dalam prosesnya!

Sebagai tambahan, banyak teknik yang masuk ke struktur data ini adalah strategi umum untuk mempercepat solusi yang tampaknya optimal. Gagasan untuk mengkomputasi semua kueri yang mungkin pada objek berukuran kecil sering disebut Metode Empat Rusia dan dapat dilihat dalam struktur data lain seperti struktur data Fischer-Heun untuk rentang kueri minimum atau algoritma decremental untuk konektivitas pohon. Demikian pula, teknik menggunakan pohon multi-jalan seimbang yang ditambah dengan faktor percabangan logaritmik muncul dalam konteks lain, seperti struktur data deterministik asli untuk konektivitas grafik dinamis, di mana pendekatan seperti itu digunakan untuk mempercepat permintaan konektivitas dariHAI(catatann) untuk HAI(catatanncatatancatatann).

templatetypedef
sumber