Hitung ketinggian pohon radix

8

pengantar

Sebuah pohon radix , juga dikenal sebagai trie dikompresi atau pohon awalan dikompresi, adalah struktur data seperti pohon untuk menyimpan satu set string. Ujung-ujung pohon diberi label oleh string yang tidak kosong, dan setiap node adalah terminal atau non-terminal. String yang berisi pohon persis label semua jalur dari root ke terminal node. Pohon harus dalam bentuk normal yang ditentukan oleh kondisi berikut:

  • Semua node non-root nonterminal memiliki setidaknya dua anak.
  • Untuk setiap node, semua tepi keluar memiliki karakter pertama yang berbeda.

Sebagai contoh, di sini adalah pohon radix yang berisi set ["test", "testing", "tested", "team", "teams", "technical", "sick", "silly"], dengan (N)mewakili simpul nonterminal dan (T)terminal simpul:

-(N)-te-(N)-st-(T)-ing-(T)
  |      |      | 
  |      |      +-ed-(T)
  |      |
  |      +-am-(T)-s-(T)
  |      |
  |      +-chnical-(T)
  |
  +-si-(N)-ck-(T)
        |
        +-lly-(T)

Dalam tantangan ini, tugas Anda adalah menghitung ketinggian pohon, mengingat string sebagai input.

Memasukkan

Input Anda adalah daftar string surat ASCII huruf kecil yang tidak kosong. Itu tidak akan berisi duplikat, tetapi mungkin dalam urutan apa pun. Mungkin berisi string kosong. Anda dapat mengambil input dalam format apa pun yang masuk akal.

Keluaran

Output Anda akan menjadi panjang jalur root-to-leaf terpanjang di pohon radix yang sesuai, diukur dalam jumlah node yang dikandungnya.

Dalam contoh di atas, output yang benar adalah 4, sesuai dengan jalur

(N)-te-(N)-st-(T)-ing-(T)
(N)-te-(N)-st-(T)-ed-(T)
(N)-te-(N)-am-(T)-s-(T)

yang berisi 4 node.

Contoh lebih lanjut

Berikut adalah beberapa contoh pohon radix:

[""]
-(T)

["","fuller"]
-(T)-fuller-(T)

["","full","fuller"]
-(T)-full-(T)-er-(T)

["full","fuller"]
-(N)-full-(T)-er-(T)

["full","filler"]
-(N)-f-(N)-ull-(T)
        |
        +-iller-(T)

Aturan dan penilaian

Anda dapat menulis program atau fungsi lengkap. Ini adalah kode golf, sehingga jumlah byte terendah menang.

Anda dapat menggunakan built-in atau pustaka yang Anda inginkan, tetapi ingat untuk memasukkan semua importdll di dalam jumlah byte Anda. Pustaka pihak ketiga - yang tidak termasuk dalam pemasangan standar bahasa Anda - diizinkan, tetapi harus dicantumkan dalam header secara terpisah, misalnya Python + pytrie0.2, 60 byte .

Uji kasus

[""] -> 1
["fuller"] -> 2
["","fuller"] -> 2
["","full","fuller"] -> 3
["full","fuller"] -> 3
["full","filler"] -> 3
["full","filler","filter"] -> 4
["full","filler","fi","filter"] -> 5
["test","testing","tested","team","teams","technical","sick","silly"] -> 4
["a","aaaa","aabbaa","aabbaab","abaaa","aab","aabbb","aabba"] -> 8
["dbdbaca","ab","a","caaabaaa","adbbabdb","dbdbdbaca","dbbadbacaba","db"] -> 4
["db","dbbdbb","dbaa","cabcacaa","","acaabcacab","b","abaaaca","bacaaaaa"] -> 3
["aabaabdbb","bacaabadbbdb","abb","aabaa","ab","bcadbb","adbbcaaadbbb","caaa","bbdbcacadbab","dbbdbdb"] -> 4
["bbcaaabbbabbcadbbacadbbdbdb","b","bbbbaaaaaababa","ca","bb","bdbbacadbbdbbdbbababaacaca","abbaabbabcabaaa","bbbacacacabcacacabaaabb","bbcaaaab","bbbbcaacaadbcaaa","babbabcadbdbacacabbcacab","abcabbbaacadbcadb","bbcabbcadbcacaacaadbadbcaadb","dbbbdbbdbacaabbacabcadbdbacaca","bbaabdbdb","cabcadbbbadbadbbaadbcaca","adbadbadbdbcacadbdbbcaadbcaca","abaabbcab","aaabcaabcaab","bacacabcacaacadbadbb"] -> 6
Zgarb
sumber
Dalam contoh pertama Anda, saya merasa "saya" harus diikuti oleh simpul dengan dua anak, satu dengan - "" - (T) dan yang lainnya dengan - "s" - (T). (Bandingkan dengan "lambat" / "lambat" pada contoh kedua pada halaman yang Anda tautkan.) Namun, ini tidak akan memengaruhi panjang jalur root-to-leaf terpanjang.
Greg Martin
@GregMartin Halaman Wikipedia memiliki implementasi yang sedikit berbeda. Saya merasa yang ini lebih alami, dan seperti yang Anda katakan, itu tidak memengaruhi ketinggian.
Zgarb

Jawaban:

2

JavaScript (Firefox 30-57), 137 byte

f=(a,b=["",...a],s=new Set(b.map(w=>w[0])))=>b.length>1?(s.size>1)+Math.max(...(for(c of s)f(a,[for(w of b)if(w&&w[0]==c)w.slice(1)]))):1

Pasti ada yang salah dengan algoritme saya karena sepertinya saya harus menggunakan case-string parameter kosong.

Neil
sumber
Dalam solusi referensi saya, string kosong juga merupakan kasus khusus. Itu karena simpul root memiliki aturannya sendiri.
Zgarb
Saya agak harus membuat case khusus juga, tetapi case khusus itu hanya satu karakter dalam solusi saya ( .pada akhir baris pertama).
Martin Ender
1

Retina , 69 55 byte

Linefeed tambahan sangat penting.

m`.(?<=(?=\D*^\1(?!\2))\D*^(.*)(.))|^.
:$&
T`w
O`
A-2`

Input adalah daftar yang dipisahkan oleh linefeed.

Kinerja dapat ditingkatkan secara signifikan dengan memasukkan \Asebelum yang terakhir \Dpada baris pertama.

Penjelasan

Node dimasukkan ke dalam kata di tiga tempat:

  • Awal mula.
  • Setelah awalan terpanjang dibagikan dengan kata lain. Yaitu, awalan bersama setelah kedua kata berbeda.
  • Tamat.

Di Retina, itu cenderung lebih pendek untuk diproduksi N+1ketika Anda menghitung Nsesuatu, jadi kami mengabaikan yang di akhir. Namun, untuk kasus input kosong, kita juga harus mengabaikan awal, karena awal dan akhir adalah sama.

Untuk melakukan penghitungan aktual, kami menyisipkan :ke setiap tempat di mana ada simpul. Kemudian kita cukup menemukan jumlah maksimum :dalam kata dan mengembalikan yang ditambah 1. Berikut adalah bagaimana kode melakukannya:

m`.(?<=(?=\D*^\1(?!\2))\D*^(.*)(.))|^.
:$&

Ini mendeteksi semua node. Ini cocok dengan karakter. Kemudian memasuki tampilan di belakang yang menangkap karakter itu ke dalam grup 2dan awalan sebelum ke dalam grup 1. Kemudian semuanya berjalan ke awal string untuk memulai lookahead, yang memeriksa bahwa ia dapat menemukan awalan di suatu tempat di mana itu tidak diikuti oleh karakter yang diambil. Jika kami menemukan kecocokan ini kami menyisipkan :di depan karakter. Kami juga mencocokkan karakter pertama dari kata saat ini untuk menyisipkan a :di awal kata-kata yang tidak kosong.

T`w

Ini menghapus semua huruf dan hanya meninggalkan :.

O`

Ini memilah-milah garis, membawa kedalaman maksimum ke ujung.

A-2`

Ini membuang semua kecuali baris terakhir.

Dan garis kosong di bagian akhir menghitung jumlah kecocokan kosong di garis itu, yang merupakan satu lebih dari jumlah titik dua di dalamnya.

Cobalah online! (Baris pertama memungkinkan suite tes yang dipisahkan dengan linefeed, di mana setiap kasus uji menggunakan pemisahan koma sebagai gantinya.)

Martin Ender
sumber