Bölüm 5: Trie Veri Yapısı
Giriş
Öğrenme Çıktıları
Trie'nin kök, düğüm, kenar ve kelime sonu işaretinden oluşan yapısını açıklamak; bir kelime kümesinin trie'sini çizmek.
Ekleme, arama, önek sorgusu, otomatik tamamlama ve silme işlemlerini Java ile yazmak ve adım adım izlemek.
İşlemlerin O(L) zamanını ve O(N · M) belleğini gerekçelendirmek; trie'yi hash tablosu ve BST ile karşılaştırmak.
Sıkıştırılmış trie, sonek trie'si ve sonek dizisinin hangi sorunu çözdüğünü açıklamak.
Trie Kavramı
Trie (Önek Ağacı, Prefix Tree)
- Dizgileri (string) hızlı arama yapılabilecek biçimde saklayan ağaç benzeri bir veri yapısıdır.
- Kök düğüm boştur; kökten aşağı her adım bir karakteri temsil eder.
- Kelimeler, kökten başlayan yollarla saklanır; ortak önekler (prefix) tek kez saklanır.
- Kullanım alanları: otomatik tamamlama, yazım denetimi, IP yönlendirme.
Trie Kavramı
Neden Trie?
Bir sözlükte "an" ile başlayan tüm kelimeleri bulmak istiyoruz. Farklı yapılar bu soruya nasıl yanıt verir?
Trie Kavramı
Temel Bileşenler
kelimeSonu (end of word): bu düğümde bir kelimenin bittiğini belirtir.Renkli düğüm "an" önekini temsil eder; "an" bir kelime değildir (işaretsiz), ama "and" ve "ant"in önekidir.
Trie Kavramı
Örnek: Yedi Kelimelik Trie
| Kelimeler |
|---|
| ab · aba · abc |
| ad |
| ba · bad · bag |
7 kelime, toplam 18 karakter → yalnızca 9 düğüm (+ kök).
kelimeSonu işareti şarttır.Trie Kavramı
Örnek: Değer Taşıyan Trie
| Anahtar | Değer | Anahtar | Değer |
|---|---|---|---|
| A | 15 | tea | 3 |
| i | 11 | ted | 4 |
| in | 5 | ten | 12 |
| inn | 9 | to | 7 |
kelimeSonu yerine düğümde bir değer saklanır. "t" ve "te" değer taşımaz; yalnızca önektir. Büyük harf "A", 26 küçük harflik dizi yerine daha geniş bir alfabe (ör. HashMap) gerektirir.Uygulama
Trie Düğüm Sınıfı
public class TrieDugumu { TrieDugumu[] cocuk; // 'a'..'z' boolean kelimeSonu; // kelime biter mi? public TrieDugumu() { kelimeSonu = false; cocuk = new TrieDugumu[26]; } }
- Her düğüm 26 çocuk başvurusu tutar; başlangıçta hepsi
null. - Karakter düğümde saklanmaz: hangi karakter olduğu, düğümün ebeveyninin hangi indisinde durduğundan anlaşılır.
kelimeSonu: kökten buraya gelen yol bir kelime mi?
and, ant, dad, do eklendikten sonra kökün cocuk dizisi: 26 hücreden yalnızca 2'si dolu (⁄ = null).
Uygulama
Karakterden İndise: ch − 'a'
| ch | Unicode | ch − 'a' |
|---|---|---|
| 'a' | 97 | 0 |
| 'd' | 100 | 3 |
| 'n' | 110 | 13 |
| 'o' | 111 | 14 |
| 't' | 116 | 19 |
| 'z' | 122 | 25 |
- Java'da
charbir sayıdır;ch - 'a'küçük harfi 0..25 aralığına eşler. - Çocuğa erişim dizi indisiyle O(1)'dir:
dugum.cocuk[ch - 'a']. - "and" için sırasıyla
cocuk[0],cocuk[13],cocuk[3]kullanılır.
'A' - 'a' = −32, 'ç' - 'a' = 134 → ArrayIndexOutOfBoundsException. Büyük harf ve Türkçe karakter için girdi dönüştürülmeli ya da HashMap kullanılmalı.Ekleme
Ekleme (Insert)
public void ekle(String kelime) { TrieDugumu dugum = kok; for (char ch : kelime.toCharArray()) { int i = ch - 'a'; if (dugum.cocuk[i] == null) dugum.cocuk[i] = new TrieDugumu(); dugum = dugum.cocuk[i]; } dugum.kelimeSonu = true; }
- Kökten başla.
- Kelimenin her karakteri için ilgili çocuğa bak:
cocuk[ch − 'a']. - Çocuk
nullise yeni düğüm oluştur; varsa (ortak önek) mevcut düğümü kullan. - O çocuğa ilerle.
- Karakterler bitince son düğümde
kelimeSonu = trueyap.
Ekleme · Adım adım
Ekleme Adım Adım: and, ant, dad, do
Başlangıçta trie yalnızca kökten oluşur; kökün 26 çocuğunun hepsi null, kelimeSonu = false.
"and" ekleniyor, karakter 'a': cocuk[0] null → yeni düğüm oluşturulur ve ona ilerlenir.
"and" ekleniyor, karakter 'n': cocuk[13] null → yeni düğüm oluşturulur ve ona ilerlenir.
"and" ekleniyor, karakter 'd': cocuk[3] null → yeni düğüm oluşturulur ve ona ilerlenir.
Karakterler bitti: son düğümde kelimeSonu = true (çift çember). "and" eklendi. Kökten itibaren cocuk[0] → cocuk[13] → cocuk[3] yolu kuruldu.
"ant" ekleniyor, karakter 'a': cocuk[0] dolu → mevcut "a" düğümüne ilerlenir (ortak önek).
"ant" ekleniyor, karakter 'n': cocuk[13] dolu → mevcut "an" düğümüne ilerlenir (ortak önek).
"ant" ekleniyor, karakter 't': cocuk[19] null → yeni düğüm oluşturulur ve ona ilerlenir.
Karakterler bitti: son düğümde kelimeSonu = true (çift çember). "ant" eklendi. Yalnızca 1 yeni düğüm gerekti: "an" öneki paylaşıldı.
"dad" ekleniyor, karakter 'd': cocuk[3] null → yeni düğüm oluşturulur ve ona ilerlenir.
"dad" ekleniyor, karakter 'a': cocuk[0] null → yeni düğüm oluşturulur ve ona ilerlenir.
"dad" ekleniyor, karakter 'd': cocuk[3] null → yeni düğüm oluşturulur ve ona ilerlenir.
Karakterler bitti: son düğümde kelimeSonu = true (çift çember). "dad" eklendi.
"do" ekleniyor, karakter 'd': cocuk[3] dolu → mevcut "d" düğümüne ilerlenir (ortak önek).
"do" ekleniyor, karakter 'o': cocuk[14] null → yeni düğüm oluşturulur ve ona ilerlenir.
Karakterler bitti: son düğümde kelimeSonu = true (çift çember). "do" eklendi. Son durum: 4 kelime, 11 karakter, kök hariç 8 düğüm.
Ekleme · Kodu adım adım çalıştır
ekle("ant"): Kodu Adım Adım İzle
Trie'de yalnızca "and" var. dugum kökten başlar.
Karakter 'a' → i = 'a' − 'a' = 0.
dugum.cocuk[0] null değil → yeni düğüm gerekmez.
dugum artık "a" düğümü.
Karakter 'n' → i = 'n' − 'a' = 13.
dugum.cocuk[13] null değil → yeni düğüm gerekmez.
dugum artık "an" düğümü.
Karakter 't' → i = 't' − 'a' = 19.
dugum.cocuk[19] == null → koşul doğru.
Yeni bir TrieDugumu oluşturulup cocuk[19]'e bağlanır (kelimeSonu = false).
dugum artık "ant" düğümü.
Döngü bitti: dugum.kelimeSonu = true. "ant" eklendi; yalnızca 1 düğüm oluşturuldu.
public void ekle(String kelime) { TrieDugumu dugum = kok; for (char ch : kelime.toCharArray()) { int i = ch - 'a'; if (dugum.cocuk[i] == null) dugum.cocuk[i] = new TrieDugumu(); dugum = dugum.cocuk[i]; } dugum.kelimeSonu = true; }
Arama
Arama (Search)
public boolean ara(String kelime) { TrieDugumu dugum = kok; for (char ch : kelime.toCharArray()) { int i = ch - 'a'; if (dugum.cocuk[i] == null) return false; dugum = dugum.cocuk[i]; } return dugum.kelimeSonu; }
- Kökten başlanır.
- Her karakter için ilgili dala (çocuğa) gidilir.
- Dal yoksa (
null) kelime trie'de yoktur.
- Dal yoksa (
- Kelimenin sonuna gelince
kelimeSonudenetlenir:true→ kelime bulundu;false→ kelime yok; yalnızca var olan bir kelimenin önekidir.
Arama · Kodu adım adım çalıştır
ara("dad"): Kodu Adım Adım İzle
Trie: and, ant, dad, do. dugum kökten başlar.
Karakter 'd' → i = 3.
cocuk[3] null değil → dal var, devam.
dugum = "d".
Karakter 'a' → i = 0.
cocuk[0] null değil → dal var, devam.
dugum = "da".
Karakter 'd' → i = 3.
cocuk[3] null değil → dal var, devam.
dugum = "dad".
Kelime bitti; dugum.kelimeSonu = true → true döner (kelime bulundu).
public boolean ara(String kelime) { TrieDugumu dugum = kok; for (char ch : kelime.toCharArray()) { int i = ch - 'a'; if (dugum.cocuk[i] == null) return false; dugum = dugum.cocuk[i]; } return dugum.kelimeSonu; }
Arama
Aramanın Üç Olası Sonucu
kelimeSonu = false: "da" yalnızca önek.cocuk[6] ('g') null: dal yok, erken çıkış.Kesikli kırmızı çember: aranan ama trie'de bulunmayan düğüm.
Arama
Önek Sorgusu: onekVarMi (startsWith)
public boolean onekVarMi(String onek) { TrieDugumu dugum = kok; for (char ch : onek.toCharArray()) { int i = ch - 'a'; if (dugum.cocuk[i] == null) return false; dugum = dugum.cocuk[i]; } return true; // ara: dugum.kelimeSonu }
| Sorgu | ara | onekVarMi |
|---|---|---|
| "dad" | true | true |
| "da" | false | true |
| "an" | false | true |
| "dog" | false | false |
Arama · Kodu adım adım çalıştır
Otomatik Tamamlama: tamamla("te")
Önce dugumBul("te") kökten t → e inerek "te" düğümünü bulur (önek sorgusu gibi).
"te" düğümünden başlayarak alt ağaç derinlik öncelikli gezilir.
"te" bir kelime değil (kelimeSonu = false) → listeye eklenmez.
i = 0: cocuk[0] ('a') dolu → yol = "tea".
Özyinelemeli çağrı: topla("tea").
"tea" işaretli → sonuc'a eklenir. Çocuğu yok; döngü 26 indisi boş geçer.
Çağrı döndü; son harf silinir (yol = "te") → geri izleme (backtracking).
i = 3: cocuk[3] ('d') dolu → yol = "ted".
Özyinelemeli çağrı: topla("ted").
"ted" işaretli → sonuc'a eklenir. Çocuğu yok; döngü 26 indisi boş geçer.
Çağrı döndü; son harf silinir (yol = "te") → geri izleme (backtracking).
i = 13: cocuk[13] ('n') dolu → yol = "ten".
Özyinelemeli çağrı: topla("ten").
"ten" işaretli → sonuc'a eklenir. Çocuğu yok; döngü 26 indisi boş geçer.
Çağrı döndü; son harf silinir (yol = "te") → geri izleme (backtracking).
Döngü bitti; tamamla("te") → [tea, ted, ten]. İndis sırası (a < d < n) sayesinde sonuçlar alfabetik sıradadır.
List<String> tamamla(String onek) {
List<String> sonuc = new ArrayList<>();
TrieDugumu d = dugumBul(onek);
if (d != null)
topla(d, new StringBuilder(onek), sonuc);
return sonuc;
}
void topla(TrieDugumu d, StringBuilder yol,
List<String> sonuc) {
if (d.kelimeSonu) sonuc.add(yol.toString());
for (int i = 0; i < 26; i++)
if (d.cocuk[i] != null) {
yol.append((char) ('a' + i));
topla(d.cocuk[i], yol, sonuc);
yol.setLength(yol.length() - 1);
}
}Arama
Deneyin: Trie Üzerinde İşlemler
Yalnızca a–z küçük harfler (en fazla 10 harf, 14 kelime). Çift çember: kelime sonu · turuncu: son ziyaret edilen düğüm · kesikli kırmızı: bulunamayan dal. Enter = ekle.
Silme
Silme (Delete): Üç Durum
kelimeSonu = false yapılır, düğüm silinmez.Cevabı göster
Yalnızca son 'p' düğümünün kelimeSonu işareti kaldırılır. Düğüm silinemez, çünkü "apple" onun altından devam eder (durum 1).
Silme · Adım adım
Silme Adım Adım: app, apple, apt
Başlangıç: app, apple, apt (kök hariç 6 düğüm). Aşağıdaki iki senaryo bu trie'den başlar.
sil("app"): a → p → p yolu izlenir; "app" düğümü işaretli, yani kelime var.
kelimeSonu = false. Düğümün çocuğu ('l') olduğu için silinmez → durum 1. "apple" hâlâ bulunur.
sil("apple") (yeniden ilk trie'den): yol a-p-p-l-e izlenir; "apple" bulundu.
'e' düğümünün işareti kalkar; çocuğu yok → ebeveyn onu siler (cocuk[4] = null).
'l' düğümü artık çocuksuz ve işaretsiz → o da silinir.
"app" düğümü işaretli (başka bir kelime) → silme burada durur. Sonuç: app, apt; kök hariç 4 düğüm (durum 2).
Silme
Silme: Özyinelemeli Kod
// true: ebeveyn d'yi silebilir boolean sil(TrieDugumu d, String k, int j) { if (j == k.length()) { // kelime bitti if (!d.kelimeSonu) return false; d.kelimeSonu = false; return bosMu(d); // çocuksuz mu? } int i = k.charAt(j) - 'a'; TrieDugumu c = d.cocuk[i]; if (c == null) return false; // kelime yok if (sil(c, k, j + 1)) { d.cocuk[i] = null; // çocuğu sil return !d.kelimeSonu && bosMu(d); } return false; }
- Çağrı:
sil(kok, kelime, 0); kökün dönüş değeri yok sayılır. - Önce kelimenin sonuna inilir, silme kararları dönüşte (aşağıdan yukarı) verilir.
- Düğüm, ancak çocuğu yoksa ve işaretsizse silinir.
bosMu(d): 26 çocuğun hepsi null mı? (O(M)).- Zaman: O(L · M) dizi ile; çocuk sayacı tutulursa O(L).
Analiz
Karmaşıklık
| İşlem | Zaman | Açıklama |
|---|---|---|
| ekle(kelime) | O(L) | Her karakter için bir adım; en fazla L yeni düğüm |
| ara(kelime) | O(L) | Dal yoksa daha erken biter |
| onekVarMi(onek) | O(P) | P: önek uzunluğu |
| tamamla(onek) | O(P + S · M) | S: önek düğümünün alt ağacındaki düğüm sayısı |
| sil(kelime) | O(L · M) | bosMu 26 hücreyi tarar; çocuk sayacıyla O(L) |
Analiz
Bellek: Sayısal Örnek
Trie: and, ant, dad, do
| Toplam karakter | 3 + 3 + 3 + 2 = 11 |
| Düğüm sayısı N | 1 (kök) + 8 = 9 |
| Çocuk başvurusu | 9 × 26 = 234 |
| Dolu başvuru | 8 (kenar sayısı) |
| Boş (null) başvuru | 226 (≈ %97) |
Analiz
Avantajlar ve Dezavantajlar
Avantajlar
- Hızlı önek (prefix) tabanlı arama: otomatik tamamlama.
- Kelime arama O(L) zaman (L: kelime uzunluğu).
- Çakışan önekler tek kez saklanır: bellek paylaşımı.
- Gezinme kelimeleri sözlük sırasında verir; hash çakışması yoktur.
Dezavantajlar
- Yüksek bellek tüketimi, özellikle büyük alfabelerde.
- Bellek karmaşıklığı O(N · M) (N: düğüm sayısı, M: alfabe boyutu).
- Ortak öneki az olan kümelerde (ör. rastgele anahtarlar) kazanç yoktur.
- Çok sayıda küçük nesne: önbellek (cache) dostu değildir.
Analiz
Çocukları Saklamanın Yolları
| Gösterim | Çocuğa erişim | Düğüm başına bellek | Not |
|---|---|---|---|
TrieDugumu[26] dizi | O(1) | M başvuru | Basit, hızlı; seyrek düğümlerde israf |
HashMap<Character, TrieDugumu> | O(1) ort. | çocuk sayısı kadar | Her alfabe (Türkçe, Unicode) çalışır; sıra korunmaz |
TreeMap / sıralı liste | O(log M) | çocuk sayısı kadar | Alfabetik gezinme korunur |
| Üçlü arama trie'si (TST) | O(log M) ort. | 3 başvuru | Her düğümde küçük / eşit / büyük bağlantısı |
dugum.cocuk[i] yerine dugum.cocuk.get(ch) gibi bir çağrı gelir. Seçim: alfabe boyutu, bellek ve sıralı çıktı ihtiyacına göre yapılır.Analiz
Trie mi, Hash Tablosu mu, BST mi?
| İşlem (n kelime, uzunluk L) | Trie | Hash tablosu | Dengeli BST |
|---|---|---|---|
| Tam kelime arama | O(L) | O(L) ortalama | O(L · log n) |
| Önek sorgusu | O(P) | desteklenmez | O(P · log n) |
| Önekle başlayan k kelime | O(P + S · M) | tüm tabloyu tara | O(P · log n + k · L) |
| Sıralı listeleme | DFS, O(N · M) | sıralama gerekir | kök ortada, O(n) |
| En kötü durum | O(L) | O(n · L) (çakışma) | O(L · log n) |
| Bellek | yüksek | düşük | düşük |
Hash tablosu da kelimenin hash değerini hesaplamak için L karakterin tümünü okur; bu yüzden tam aramada ikisi aynı mertebededir. Trie'nin farkı önek ve sıra sorgularındadır. S: önek düğümünün alt ağacındaki düğüm sayısı.
Uygulamalar ve Türevler
Kullanım Alanları
Uygulamalar ve Türevler
Sıkıştırılmış Trie (Radix / Patricia)
- Tek çocuklu ve işaretsiz düğüm zincirleri tek bir kenarda birleştirilir; kenar artık bir alt dizgi taşır ("an", "ad").
- Her iç düğümün en az 2 çocuğu (ya da kelime sonu işareti) olduğundan düğüm sayısı O(n) olur (n: kelime sayısı).
- Patricia (Morrison, 1968) bu fikrin ikili alfabe sürümüdür; IP yönlendirme tablolarında kullanılır.
Uygulamalar ve Türevler
Sonek Trie'si (Suffix Trie)
T = "abab" metninin tüm sonekleri bir trie'ye eklenir:
abab · bab · ab · b
- P, T'nin bir alt dizgisi ⇔ P, bir sonekin öneki ⇔ P kökten başlayan bir yol.
- Sorgu:
onekVarMi(P)→ O(m) (m = |P|), metnin uzunluğundan bağımsız. Örn. "ba" var, "bb" yok. - Bedel: n uzunluklu metin için O(n²) düğüm olabilir.
- Sonek ağacı (suffix tree) = sıkıştırılmış sonek trie'si: O(n) düğüm, Ukkonen algoritmasıyla O(n) zamanda kurulur.
Uygulamalar ve Türevler
Sonek Dizisi (Suffix Array)
| sıra | SA[sıra] | sonek |
|---|---|---|
| 0 | 6 | a |
| 1 | 2 | abama |
| 2 | 0 | alabama |
| 3 | 4 | ama |
| 4 | 3 | bama |
| 5 | 1 | labama |
| 6 | 5 | ma |
- Sonek trie'sinin bellek dostu alternatifi: soneklerin başlangıç indisleri, sözlük sırasına göre dizilir.
- "alabama" → SA = [6, 2, 0, 4, 3, 1, 5].
- Kurulum: tüm sonekleri oluşturup
Arrays.sortile sırala → O(n² log n) en kötü; özel algoritmalarla O(n log n) ya da O(n). - Arama: SA üzerinde ikili arama → O(m log n). Örn. "ama" için 3. sıradaki sonek (indis 4) bulunur.
- Yalnızca n tamsayı: trie'deki O(n²) düğüm yerine O(n) bellek.
Özet
Özet
| Konu | Hatırlanacaklar |
|---|---|
| Yapı | boş kök; her kenar bir karakter; kelime = kökten yol; ortak önekler paylaşılır |
| Düğüm | TrieDugumu[26] cocuk + boolean kelimeSonu; indis = ch − 'a' |
| Ekleme | yoksa düğüm oluştur, varsa ilerle; sonda işaretle — O(L) |
| Arama | dal yoksa false; sonda kelimeSonu döner — O(L) |
| Önek | aynı yol, işaret denetimi yok — O(P); tamamla = önek düğümünden DFS |
| Silme | işareti kaldır; çocuksuz ve işaretsiz düğümleri aşağıdan yukarı sil |
| Bellek | O(N · M); seyrek düğümlerde HashMap / TST / sıkıştırılmış trie |
| Türevler | radix/Patricia trie, sonek trie'si → sonek ağacı, sonek dizisi |
Özet
Etkileşimli Simülatörler
Özet
Sık Yapılan Hatalar
kelimeSonu'nu unutmakAramada yalnızca yolun varlığına bakmak her öneki kelime sayar: "da" bulunmuş gibi görünür.'A' − 'a' = −32, 'ş' − 'a' = 254: dizi sınırı aşılır. Girdiyi küçük harfe çevirin ya da HashMap kullanın.Özet
Örnek Problemler
Kelimeler sırayla eklenir: car, cart, care, cat, dog (26 elemanlı dizili trie).
- Trie'yi çizin. Kök dahil kaç düğüm vardır?
ara("ca")veonekVarMi("ca")ne döndürür?tamamla("car")sonucunu sırasıyla yazın.sil("car")ve (ilk trie'den)sil("cart")kaç düğüm siler?- Toplam kaç çocuk başvurusu
null'dır? - "banana" metninin sonek dizisini bulun.
Cevapları göster
- c-a-r(•)-t(•), car-e(•), ca-t(•); d-o-g(•) → kök hariç 9, kök dahil 10 düğüm (17 karakter).
ara("ca")= false ("ca" işaretsiz);onekVarMi("ca")= true.- [car, care, cart] — DFS önce düğümün kendisini, sonra çocukları indis sırasıyla ('e' < 't') verir.
sil("car"): 0 düğüm (yalnızca işaret kalkar);sil("cart"): 1 düğüm ('t'), "car" işaretli olduğu için durur.- 10 × 26 = 260 başvuru, 9'u dolu (kenar sayısı) → 251 null.
- Sonekler sıralanır: a, ana, anana, banana, na, nana → SA = [5, 3, 1, 0, 4, 2].
Özet
Alıştırmalar
int kelimeSayisi(TrieDugumu d): trie'deki kelime sayısını bulun.int onekSayisi(String onek): bu önekle başlayan kelime sayısını O(P)'de döndürün.String enUzunOrtakOnek(): trie'deki tüm kelimelerin en uzun ortak önekini bulun.- Çocukları
HashMap<Character, TrieDugumu>ile saklayan, Türkçe karakterleri destekleyen trie yazın. - A, to, tea, ted, ten, i, in, inn anahtarlarının trie'sinde kök dahil kaç düğüm vardır?
- Sonek trie'si ile "abab" içinde "bab" ve "bb" alt dizgilerini arayın; kaç karşılaştırma yapılır?
Cevaplar / ipuçları
- DFS:
(d.kelimeSonu ? 1 : 0)+ tüm dolu çocuklarınkelimeSayisitoplamı. O(N · M). - Düğüme
int gecissayacı ekleyin;ekleher geçtiği düğümde artırsın. Önek düğümünün sayacı = cevap. - Kökten inin: düğümün tek çocuğu var ve
kelimeSonufalse iken ilerleyin; geçilen karakterler cevaptır. cocuk.get(ch)/cocuk.computeIfAbsent(ch, x -> new TrieDugumu()); indis hesabı kalkar.- A, t, to, te, tea, ted, ten, i, in, inn = 10 düğüm + kök = 11.
- "bab": b → a → b yolu var → bulundu (3 adım). "bb": b'den sonra 'b' dalı yok → yok (2 adım).
Özet
Kaynaklar
- Sedgewick ve Wayne, Algorithms, 4. baskı, 2011 (Bölüm 5.2: Tries).
- Cormen, Leiserson, Rivest ve Stein, Introduction to Algorithms, 4. baskı, 2022.
- E. Fredkin, "Trie Memory", Communications of the ACM 3(9), 1960.
- D. R. Morrison, "PATRICIA — Practical Algorithm To Retrieve Information Coded in Alphanumeric", Journal of the ACM 15(4), 1968.
- U. Manber ve G. Myers, "Suffix Arrays: A New Method for On-Line String Searches", SIAM Journal on Computing 22(5), 1993.
- D. Gusfield, Algorithms on Strings, Trees, and Sequences, Cambridge University Press, 1997.