Bölüm 5: Dizgi Algoritmaları

Bölüm 5: Dizgi Algoritmaları · Çalışma Soruları
Kaba kuvvetKMP ve LPS tablosuBoyer-Moore ve HorspoolRabin-KarpRLELZW ve LZ78
Sercan KÜLCÜ

Çıktı Sorusu · Kaba Kuvvet

Soru 1: Kaç Karşılaştırma?

Dersteki kabaKuvvet metodu kabaKuvvet("abracacadabra", "cad") çağrısında hangi değeri döndürür ve toplam kaç karakter karşılaştırması yapar?

int kabaKuvvet(String t, String p) {
  int n = t.length(), m = p.length();
  for (int i = 0; i <= n - m; i++) {
    int j = 0;
    while (j < m &&
      t.charAt(i + j) == p.charAt(j))
      j++;
    if (j == m) return i;
  }
  return -1;
}
Cevabı göster

Dönüş: 6 · karşılaştırma: 11

  • s = 0, 1, 2, 3: ilk karakter (a, b, r, a) ≠ c → 4 × 1 = 4
  • s = 4: c = c, a = a, c ≠ d → 3
  • s = 5: a ≠ c → 1
  • s = 6: c, a, d eşleşir → 3; j == m olduğu için 6 döner
abracacadabra0123456789101112s=4cads=5cads=6cad

4 + 3 + 1 + 3 = 11. Uyuşmazlıkta öğrenilen bilgi atılır; örüntü her seferinde yalnızca 1 kayar.

Çoktan Seçmeli · Kaba Kuvvet

Soru 2: En Kötü Durum

Metin 15 tane adan oluşuyor ("aaa…a", n = 15), örüntü "aaaab". Kaba kuvvet toplam kaç karakter karşılaştırması yapar?

B: Geçerli kaymalar 0..n − m, yani 15 − 5 + 1 = 11 hizadır; her hizada dört a eşleşir ve uyuşmazlık son karakterde çıkar → 11 · 5 = 55. 75, n · m üst sınırıdır; 50, son hizanın (s = 10) unutulduğu sayımdır; 11 yalnızca hiza sayısıdır.

Çoktan Seçmeli · Kaba Kuvvet

Soru 3: Döngü Sınırı Hatası

kabaKuvvet metodundaki i <= n - m koşulu yanlışlıkla i < n - m yazılırsa aşağıdaki çağrılardan hangisi yanlış sonuç (−1) döndürür?

C: n = 5, m = 2 için doğru kaymalar 0..3'tür; hatalı koşul yalnızca 0, 1, 2'yi dener. "em" yalnızca s = 3 = n − m konumunda geçtiği için bulunamaz. "le" s = 2'de olduğu için hâlâ bulunur.

Adım Adım Çalıştırma · Kaba Kuvvet

Soru 4: kabaKuvvet İzleme

kabaKuvvet("AABAABAAC", "AAC") hangi değeri döndürür, kaç karakter karşılaştırması yapılır?

AABAABAAC012345678AAC

n = 9, m = 3: geçerli kaymalar i = 0..6. Örüntü metnin altına i = 0 hizasında yerleşecek.

AABAABAAC012345678AAC

i = 0: 2 karakter eşleşti, t[2] = 'B' ≠ p[2] = 'C' → örüntü 1 kayar.

AABAABAAC012345678AAC

i = 1: 1 karakter eşleşti, t[2] = 'B' ≠ p[1] = 'A' → örüntü 1 kayar.

AABAABAAC012345678AAC

i = 2: t[2] = 'B' ≠ p[0] = 'A' → ilk karakterde uyuşmazlık, örüntü 1 kayar.

AABAABAAC012345678AAC

i = 3: 2 karakter eşleşti, t[5] = 'B' ≠ p[2] = 'C' → örüntü 1 kayar.

AABAABAAC012345678AAC

i = 4: 1 karakter eşleşti, t[5] = 'B' ≠ p[1] = 'A' → örüntü 1 kayar.

AABAABAAC012345678AAC

i = 5: t[5] = 'B' ≠ p[0] = 'A' → ilk karakterde uyuşmazlık, örüntü 1 kayar.

AABAABAAC012345678AAC

i = 6: A, A, C üçü de eşleşti; j = 3 = m olunca while döngüsü biter.

AABAABAAC012345678AAC

j == m → 6 döndürülür. Toplam 15 karşılaştırma; aynı A'lar farklı hizalarda tekrar tekrar okundu.

int kabaKuvvet(String t, String p) {
  int n = t.length(), m = p.length();
  for (int i = 0; i <= n - m; i++) {
    int j = 0;
    while (j < m &&
      t.charAt(i + j) == p.charAt(j))
      j++;
    if (j == m) return i;
  }
  return -1;
}

Çoktan Seçmeli · KMP

Soru 5: LPS Tanımı

lpsHesapla("aaaa") hangi diziyi döndürür?

A: lps[q], P[0..q]'nun kendisine eşit olmayan (uygun) ve aynı zamanda soneki olan en uzun önekidir. "aaaa" için bu "aaa" → 3. B dizginin kendisini de sayar; D ise yalnızca tek karakterlik öneki dener.

Çıktı Sorusu · KMP

Soru 6: LPS Tablosu

"AABAACAABAA" örüntüsünün LPS tablosunu (önek fonksiyonu) bulun. q = 5 ve q = 10 için gerekçeyi yazın.

Cevabı göster PAABAACAABAA012345678910lps01012012345

lps = [0, 1, 0, 1, 2, 0, 1, 2, 3, 4, 5]

  • q = 5 (C): "AABAAC"; C ile biten bir önek yok (önekler A ile başlayıp A, AA, AAB… diye gider) → 0.
  • q = 10: "AABAACAABAA"nın sonu "AABAA" ile, başı da "AABAA" ile aynı → 5.
  • q = 6..10: "AABAA" öneki yeniden başladığından değerler 1, 2, 3, 4, 5 diye artar.

Adım Adım Çalıştırma · KMP

Soru 7: lpsHesapla İzleme

lpsHesapla("ababaca") hangi diziyi döndürür?

Pababaca0123456lps0

lps[0] = 0 her zaman (tek karakterin uygun öneki yok). k: o ana kadar eşleşen önek uzunluğu.

Pababaca0123456lps00

p[0] = 'a' ≠ p[1] = 'b' → k = 0 kalır, lps[1] = 0.

Pababaca0123456lps001

p[0] = 'a' = p[2] → k = 1, lps[2] = 1.

Pababaca0123456lps0012

p[1] = 'b' = p[3] → k = 2, lps[3] = 2.

Pababaca0123456lps00123

p[2] = 'a' = p[4] → k = 3, lps[4] = 3.

Pababaca0123456lps00123

p[3] = 'b' ≠ p[5] = 'c' → geri çekil: k = lps[2] = 1.

Pababaca0123456lps00123

p[1] = 'b' ≠ p[5] = 'c' → geri çekil: k = lps[0] = 0.

Pababaca0123456lps001230

p[0] = 'a' ≠ p[5] = 'c' → k = 0 kalır, lps[5] = 0.

Pababaca0123456lps0012301

p[0] = 'a' = p[6] → k = 1, lps[6] = 1.

Pababaca0123456lps0012301

Sonuç: lps = [0, 0, 1, 2, 3, 0, 1]. Toplam geri çekilme toplam artışı aşamaz → O(m).

int[] lpsHesapla(String p) {
  int m = p.length(), k = 0;
  int[] lps = new int[m];
  for (int q = 1; q < m; q++) {
    while (k > 0 &&
      p.charAt(k) != p.charAt(q))
      k = lps[k - 1];
    if (p.charAt(k) == p.charAt(q))
      k++;
    lps[q] = k;
  }
  return lps;
}

Çoktan Seçmeli · KMP

Soru 8: Uyuşmazlıkta Geri Çekilme

Örüntü "abcabd" için lps = [0, 0, 0, 1, 2, 0]. KMP aramasında metinle "abcab" eşleşmişken (q = 5) sıradaki metin karakteri d değil. q hangi değeri alır ve örüntü kaç konum kaymış olur?

D: q = lps[q − 1] = lps[4] = 2, çünkü "ab" eşleşen "abcab"ın hem öneki hem sonekidir; kayma 5 − 2 = 3. B, lps[q] (lps[5] = 0) kullanma hatasıdır. Metin işaretçisi i geri gitmez; "ab" yeniden karşılaştırılmaz.

Çıktı Sorusu · KMP

Soru 9: Üç Algoritma, Bir Metin

Metin "gel de geleyim", örüntü "geleyim". Kaba kuvvet, KMP ve Boyer-Moore (yalnızca kötü karakter kuralı) ilk eşleşmeyi bulana kadar kaçar karakter karşılaştırması yapar? Eşleşme hangi konumdadır?

Cevabı göster

Eşleşme s = 7. Karşılaştırmalar: kaba kuvvet 17, KMP 15, Boyer-Moore 8.

  • Kaba kuvvet: s = 0'da "gel" eşleşir, '␣' ≠ 'e' (4); s = 1..6 ilk karakterde biter (6); s = 7'de 7 → 17.
  • KMP (lps hep 0): "gel" (3), '␣' önce p[3] sonra p[0] ile (2), d, e, ␣ (3), geleyim (7) → 15. Metin hiç geri okunmaz.
  • Boyer-Moore: s = 0'da sağdan ilk karşılaştırma t[6] = '␣' ≠ 'm'; ␣ örüntüde yok → 7 kaydır; s = 7'de 7 eşleşme → 8.
gel␣de␣geleyim012345678910111213BM 1geleyimBM 2geleyim

Çoktan Seçmeli · KMP

Soru 10: KMP Neden Doğrusal?

KMP aramasında while döngüsündeki geri çekilmelerin (q = lps[q - 1]) toplam sayısı neden n'yi aşamaz?

B: Amortize argüman: q her adımda en çok 1 artar (toplam ≤ n), her geri çekilme onu en az 1 azaltır ve q ≥ 0 kalır; bu yüzden toplam geri çekilme ≤ n, arama O(n). C yanlıştır: KMP'de i hiç geri gitmez; A da yanlıştır: lps değerleri m − 1'e kadar çıkabilir.

Adım Adım Çalıştırma · KMP

Soru 11: kmpAra İzleme

kmpAra("abababca", "ababc") hangi değeri döndürür?

abababca01234567ababc

n = 8, m = 5, lps("ababc") = [0, 0, 1, 2, 0]. q: örüntünün metinle eşleşmiş önek uzunluğu.

abababca01234567ababc

p[0] = t[0] = 'a' → q = 1.

abababca01234567ababc

p[1] = t[1] = 'b' → q = 2.

abababca01234567ababc

p[2] = t[2] = 'a' → q = 3.

abababca01234567ababc

p[3] = t[3] = 'b' → q = 4.

abababca01234567ababc

p[4] = 'c' ≠ t[4] = 'a' → q = lps[3] = 2; i yerinde kalır, örüntü 2 kayar.

abababca01234567ababc

p[2] = t[4] = 'a' → q = 3.

abababca01234567ababc

p[3] = t[5] = 'b' → q = 4.

abababca01234567ababc

p[4] = t[6] = 'c' → q = 5 = m: 2 döndürülür (i − m + 1). Metin bir kez tarandı.

int kmpAra(String t, String p) {
  int n = t.length(), m = p.length();
  int[] lps = lpsHesapla(p);
  int q = 0;  // eşleşen uzunluk
  for (int i = 0; i < n; i++) {
    while (q > 0 &&
      p.charAt(q) != t.charAt(i))
      q = lps[q - 1];
    if (p.charAt(q) == t.charAt(i))
      q++;
    if (q == m)
      return i - m + 1;
  }
  return -1;
}

Çıktı Sorusu · Boyer-Moore

Soru 12: Son Görülme ve Hizalar

"TRUSTHARDTOOTHBRUSHES" metninde "TOOTH" Boyer-Moore ile (yalnızca kötü karakter kuralı, s += max(1, j − son[c])) aranıyor. Son görülme tablosunu yazın; örüntü hangi hizalarda denenir ve toplam kaç karşılaştırma yapılır?

Cevabı göster

son: T = 3, O = 2, H = 4, diğer = −1.

suyuşmazlıkkaydırma
0t[4] = T ≠ H (j = 4)4 − 3 = 1
1H, T eşleşti; t[3] = S ≠ O (j = 2)2 − (−1) = 3
4t[8] = D ≠ H (j = 4)4 − (−1) = 5
95 karakter eşleştibulundu
TRUSTHARDTOOTHBRUSHES012345678910111213141516171819201TOOTH2TOOTH3TOOTH4TOOTH

4 hiza, 1 + 3 + 1 + 5 = 10 karşılaştırma; eşleşme s = 9.

Çoktan Seçmeli · Boyer-Moore

Soru 13: max(1, …) Neden Var?

Boyer-Moore'da kaydırma s += Math.max(1, j - son[c]) yerine s += j - son[c] yazılırsa ne olur?

A: Örneğin "abacab"da c = a için son = 4'tür; uyuşmazlık j = 3'te çıkarsa 3 − 4 = −1 olur. max(1, …) en az 1 ilerlemeyi garanti eder; yoksa sonsuz döngü ya da geri gitme olur. B yanlıştır: j + 1 kaydırma güvenlidir, çünkü c'yi içeren hiçbir hiza eşleşemez.

Adım Adım Çalıştırma · Boyer-Moore

Soru 14: boyerMoore İzleme

boyerMoore("KARTAL KALKAR", "KALKAR") hangi değeri döndürür?

KARTAL␣KALKAR0123456789101112KALKAR

n = 13, m = 6. Son görülme: K = 3, A = 4, L = 2, R = 5, diğerleri −1. Karşılaştırma sağdan sola yapılacak.

KARTAL␣KALKAR0123456789101112KALKAR

s = 0: p[5] = 'R' ≠ t[5] = 'L'. Kötü karakter: 'L'.

KARTAL␣KALKAR0123456789101112KALKAR

son['L'] = 2 → max(1, 5 − 2) = 3; s = 3.

KARTAL␣KALKAR0123456789101112KALKAR

s = 3: p[5] = 'R' ≠ t[8] = 'A'. Kötü karakter: 'A'.

KARTAL␣KALKAR0123456789101112KALKAR

son['A'] = 4 → max(1, 5 − 4) = 1; s = 4.

KARTAL␣KALKAR0123456789101112KALKAR

s = 4: p[5] = 'R' ≠ t[9] = 'L'. Kötü karakter: 'L'.

KARTAL␣KALKAR0123456789101112KALKAR

son['L'] = 2 → max(1, 5 − 2) = 3; s = 7.

KARTAL␣KALKAR0123456789101112KALKAR

s = 7: R, A, K, L, A, K sağdan sola eşleşti, j = −1.

KARTAL␣KALKAR0123456789101112KALKAR

j < 0 → 7 döndürülür. 4 hiza, toplam 9 karşılaştırma (kaba kuvvet 8 hiza dener).

int boyerMoore(String t, String p) {
  int n = t.length(), m = p.length();
  int[] son = sonGorulme(p);
  int s = 0;
  while (s <= n - m) {
    int j = m - 1;
    while (j >= 0 &&
      p.charAt(j) == t.charAt(s + j))
      j--;
    if (j < 0) return s;
    s += Math.max(1,
      j - son[t.charAt(s + j)]);
  }
  return -1;
}

Çıktı Sorusu · Boyer-Moore

Soru 15: Horspool Kaydırma Tablosu

"BARBER" örüntüsü için Horspool kaydırma tablosunu kayd[c] = m − 1 − (c'nin P[0..m−2] içindeki en sağ konumu), yoksa m kuralıyla kurun. Hizanın son karakterinin altındaki metin karakteri B, R ve X olursa örüntü kaçar kaydırılır?

PBARBER012345
Cevabı göster

m = 6; tabloya yalnızca P[0..4] = B A R B E katılır:

cBAREdiğer
kayd[c]5 − 3 = 25 − 1 = 45 − 2 = 35 − 4 = 16

B → 2, R → 3, X → 6. Son karakter (R, indis 5) tabloya katılmaz; R yine de indis 2'de geçtiği için 3 kaydırır. Kaydırma, uyuşmazlığın nerede olduğuna bakmaz; hep hizanın son karakterine göre yapılır.

Çoktan Seçmeli · Boyer-Moore

Soru 16: En İyi Durum

n = 1000 karakterlik metnin hiçbir karakteri, m = 10 uzunluklu örüntüde geçmiyor. Boyer-Moore (kötü karakter kuralı) toplam kaç karakter karşılaştırması yapar?

C: Her hizada sağdan ilk karşılaştırma uyuşmaz; c örüntüde olmadığından j − (−1) = 10 kaydırılır. Hizalar s = 0, 10, …, 990 → 100 hiza × 1 = 100 ≈ n/m. 991, kaba kuvvetin en iyi durumudur (her hizada 1 karşılaştırma, kayma 1).

Çıktı Sorusu · Rabin-Karp

Soru 17: Kayan Hash

Taban B = 10, Q = 11, karakterler rakam; T = "26535", m = 3. h("265") = 265 mod 11 = 1 ve Bm−1 mod Q = 100 mod 11 = 1'dir. Kaydırma formülü hs+1 = (B · (hs − t[s] · Bm−1) + t[s+m]) mod Q ile h("653") ve h("535")'i bulun.

T2653501234
Cevabı göster
  • h("653") = (10 · (1 − 2 · 1) + 3) mod 11 = (−7) mod 11 = 4 ✓ (653 = 59 · 11 + 4)
  • h("535") = (10 · (4 − 6 · 1) + 5) mod 11 = (−15) mod 11 = 7 ✓ (535 = 48 · 11 + 7)

Her yeni pencere O(1)'de: çıkan rakam düşülür, kalanlar bir basamak sola kayar, giren rakam eklenir. Ara sonuç negatif çıkabilir; Java'da % negatif verdiği için if (th < 0) th += Q gerekir.

Çoktan Seçmeli · Rabin-Karp

Soru 18: Sahte Eşleşme

Oyuncak hash: harf değerlerinin toplamı (a = 1, b = 2, c = 3, d = 4). "adcb" metninde "bc" (hash 5) aranıyor. Hangi pencereler sahte eşleşme (spurious hit) olur?

D: Pencereler "ad" = 5, "dc" = 7, "cb" = 5. İki pencerenin hash'i örüntününkine eşittir ama karakterleri farklıdır; doğrulama ikisini de reddeder ve metinde "bc" yoktur. Toplam hash sıraya duyarsızdır ("cb" de 5 verir); bu yüzden konum ağırlıklı polinom hash kullanılır.

Adım Adım Çalıştırma · Rabin-Karp

Soru 19: rabinKarp İzleme

rabinKarp("alakart", "kar") hangi değeri döndürür; kaç pencerede karakter doğrulaması yapılır?

alakart0123456ph = 22

B = 256, Q = 101. Örüntü "kar" 3 karakterlik pencerelerle karşılaştırılacak; n − m + 1 = 5 pencere var.

alakart0123456ph = 22

h = 256² mod 101 = 88: pencereden çıkan karakterin ağırlığı.

alakart0123456th = 22 · ph = 22

ph = hash("kar") = 22; ilk pencere "ala" için th = 22.

alakart0123456th = 22 · ph = 22sahte eşleşme

s = 0: th = ph = 22 ama esit("ala", "kar") yanlış → sahte eşleşme; 3 karakter boşa karşılaştırıldı.

alakart0123456th = 2 · ph = 22

Kaydır: 'a' çıkar, 'k' girer → th = 2.

alakart0123456th = 69 · ph = 22

s = 1: th = 2 ≠ 22, karakterlere bakılmaz. Kaydır: 'l' çıkar, 'a' girer → th = 69.

alakart0123456th = 22 · ph = 22

s = 2: th = 69 ≠ 22, geç. Kaydır: 'a' çıkar, 'r' girer → th = 22.

alakart0123456th = 22 · ph = 22doğrulandı

s = 3: th = ph = 22 ve esit("kar", "kar") doğru → 3 döndürülür. 2 doğrulamadan biri boşa gitti.

int rabinKarp(String t, String p) {
  int n = t.length(), m = p.length();
  int B = 256, Q = 101, h = 1, ph = 0, th = 0;
  for (int i = 0; i < m - 1; i++)
    h = (h * B) % Q;
  for (int i = 0; i < m; i++) {
    ph = (B * ph + p.charAt(i)) % Q;
    th = (B * th + t.charAt(i)) % Q;
  }
  for (int s = 0; s <= n - m; s++) {
    if (ph == th && esit(t, p, s)) return s;
    if (s < n - m) {
      th = (B * (th - t.charAt(s) * h)
            + t.charAt(s + m)) % Q;
      if (th < 0) th += Q;
    }
  }
  return -1;
}

Çoktan Seçmeli · Rabin-Karp

Soru 20: Hash Karşılaştırmasının Sakıncası

"abracadabra" içinde "cad" aranırken Rabin-Karp örüntünün ve her pencerenin hash değerini karşılaştırıyor. Yalnızca hash değerlerini karşılaştırmanın temel sakıncası nedir?

A: Hash çakışması (sahte eşleşme) olabilir; hash eşitliği eşleşmeyi garanti etmez, bu yüzden karakter karakter doğrulama yapılır. Büyük asal Q çakışma olasılığını ≈ 1/Q'ya indirir; çok sayıda çakışmada süre O(n · m)'ye çıkar. Eşit dizgilerin hash'i her zaman eşittir (D yanlış).

Çoktan Seçmeli · Rabin-Karp

Soru 21: Çok Sayıda Örüntü

Aynı uzunlukta 500 farklı virüs imzası bir dosyada tek geçişte aranacak. Hangi yaklaşım en uygundur?

B: Pencere hash'i O(1)'de güncellenir ve HashSet'te O(1) ortalamayla aranır; bulunursa doğrulanır → beklenen O(n + k · m). A ve D dosyayı k kez tarar; C ise imzaları birleştirince hiçbir imzayı tek başına bulmaz.

Çıktı Sorusu · RLE

Soru 22: rleSikistir Çıktısı

Dersteki rleSikistir metoduyla aşağıdaki kod ne yazdırır? Her satır için sıkıştırma oranını (sıkıştırılmış / orijinal) hesaplayın.

System.out.println(rleSikistir("aaabccddddde"));
System.out.println(rleSikistir("abc"));
System.out.println(rleSikistir("zzzzzzzzzzzz"));
Cevabı göster
3a1b2c5d1e
1a1b1c
12z
  • 12 → 10 karakter: oran 10/12 ≈ 0,83
  • 3 → 6 karakter: oran 2; tekrar yoksa RLE büyütür.
  • 12 → 3 karakter: oran 0,25; sayı iki basamaklıdır, açıcı rakamları biriktirerek okumalıdır (sayi = sayi · 10 + rakam).

Çoktan Seçmeli · RLE

Soru 23: RLE Ne Zaman Büyütür?

rleSikistir aşağıdaki girdilerden hangisinin çıktısını girdiden uzun yapar?

D: Hiç ardışık tekrar yok; her karakter "1" + karakter olarak yazılır: 8 → 16 karakter (iki kat). Diğerleri küçülür: "5a5b" (10 → 4), "4a1b4a" (9 → 6), "11x1y" (12 → 5). RLE yalnızca ardışık tekrarı yakalar; "abab…" gibi tekrar eden dizgileri LZW yakalar.

Adım Adım Çalıştırma · RLE

Soru 24: rleSikistir İzleme

rleSikistir("aaabccdddd") hangi dizgiyi döndürür?

aaabccdddd0123456789ssonuc""

n = 10, sonuc boş. Her koşu (ardışık aynı karakterler) sayı + karakter olarak yazılacak.

aaabccdddd0123456789ssonuc""

Yeni koşu: c = 'a', sayac = 1 (i = 0).

aaabccdddd0123456789ssonuc3a

while 2 kez döndü: sayac = 3, i = 2. "3a" eklenir.

aaabccdddd0123456789ssonuc3a

Yeni koşu: c = 'b', sayac = 1 (i = 3).

aaabccdddd0123456789ssonuc3a1b

s[4] = 'c' ≠ 'b': while hiç dönmez. "1b" eklenir.

aaabccdddd0123456789ssonuc3a1b

Yeni koşu: c = 'c', sayac = 1 (i = 4).

aaabccdddd0123456789ssonuc3a1b2c

while 1 kez döndü: sayac = 2, i = 5. "2c" eklenir.

aaabccdddd0123456789ssonuc3a1b2c

Yeni koşu: c = 'd', sayac = 1 (i = 6).

aaabccdddd0123456789ssonuc3a1b2c4d

while 3 kez döndü: sayac = 4, i = 9. "4d" eklenir.

aaabccdddd0123456789ssonuc3a1b2c4d

Sonuç: "3a1b2c4d" (10 → 8 karakter). İç while i'yi de ilerlettiği için toplam iş O(n).

String rleSikistir(String s) {
  StringBuilder sonuc = new StringBuilder();
  int n = s.length();
  for (int i = 0; i < n; i++) {
    char c = s.charAt(i);
    int sayac = 1;
    while (i + 1 < n &&
      s.charAt(i + 1) == c) {
      sayac++;
      i++;
    }
    sonuc.append(sayac).append(c);
  }
  return sonuc.toString();
}

Adım Adım Çalıştırma · LZW

Soru 25: lzw İzleme

Başlangıç sözlüğü A = 0, B = 1 iken lzw("BABAABAAA") hangi kodları üretir?

BABAABAAAskoddizgiçıktı: —

Sözlük tek karakterlerle başlar: A = 0, B = 1; yeni dizgiler 2'den numaralanır. w = "".

BABAABAAAskoddizgiçıktı: —

"B" sözlükte (1) → w = "B"; daha uzun eşleşme aranır.

BABAABAAAskoddizgi2BAçıktı: 1

"BA" yok → w = "B" kodu 1 çıktıya; "BA" = 2 eklenir; w = "A".

BABAABAAAskoddizgi2BA3ABçıktı: 1 0

"AB" yok → w = "A" kodu 0 çıktıya; "AB" = 3 eklenir; w = "B".

BABAABAAAskoddizgi2BA3ABçıktı: 1 0

"BA" sözlükte (2) → w = "BA"; daha uzun eşleşme aranır.

BABAABAAAskoddizgi2BA3AB4BAAçıktı: 1 0 2

"BAA" yok → w = "BA" kodu 2 çıktıya; "BAA" = 4 eklenir; w = "A".

BABAABAAAskoddizgi2BA3AB4BAAçıktı: 1 0 2

"AB" sözlükte (3) → w = "AB"; daha uzun eşleşme aranır.

BABAABAAAskoddizgi2BA3AB4BAA5ABAçıktı: 1 0 2 3

"ABA" yok → w = "AB" kodu 3 çıktıya; "ABA" = 5 eklenir; w = "A".

BABAABAAAskoddizgi2BA3AB4BAA5ABA6AAçıktı: 1 0 2 3 0

"AA" yok → w = "A" kodu 0 çıktıya; "AA" = 6 eklenir; w = "A".

BABAABAAAskoddizgi2BA3AB4BAA5ABA6AAçıktı: 1 0 2 3 0

"AA" sözlükte (6) → w = "AA"; daha uzun eşleşme aranır.

BABAABAAAskoddizgi2BA3AB4BAA5ABA6AAçıktı: 1 0 2 3 0 6

Döngü bitti; kalan w = "AA" kodu 6 eklenir. Çıktı: 1 0 2 3 0 6 (9 sembol → 6 kod).

List<Integer> lzw(String s) {
  Map<String, Integer> sozluk = ilkSozluk(s);
  String w = "";
  List<Integer> kod = new ArrayList<>();
  for (char c : s.toCharArray()) {
    String wc = w + c;
    if (sozluk.containsKey(wc)) {
      w = wc;
    } else {
      kod.add(sozluk.get(w));
      sozluk.put(wc, sozluk.size());
      w = "" + c;
    }
  }
  if (!w.isEmpty()) kod.add(sozluk.get(w));
  return kod;
}

Çıktı Sorusu · LZW

Soru 26: LZW Açma

Başlangıç sözlüğü A = 0, B = 1, C = 2. LZW ile sıkıştırılmış 0 1 3 2 4 7 kod dizisini açın. Hangi kodda açıcı "henüz tanımlanmamış kod" durumuyla karşılaşır?

Cevabı göster
kodyazılansözlüğe eklenen
0A—
1B3 = AB
3AB4 = BA
2C5 = ABC
4BA6 = CB
7BAB7 = BAB (özel durum)

Sonuç: ABABCBABAB. 7 okunduğunda açıcının sözlüğü 6'ya kadardır: e = w + w[0] = "BA" + "B" = "BAB". Kontrol: lzw("ABABCBABAB") yine 0 1 3 2 4 7 verir.

Çoktan Seçmeli · LZW

Soru 27: LZ78 Çıktısı

Sözlüğü boş başlayan LZ78, "abababa" dizgisini hangi (indis, karakter) çiftlerine dönüştürür?

C: a → (0, a), 1 = a · b → (0, b), 2 = b · "ab": a var (1), ab yok → (1, b), 3 = ab · "aba": ab var (3) → (3, a), 4 = aba. LZW'nin farkı sözlüğü tüm tek karakterlerle başlatmasıdır; böylece çıktıda karakter yazmaya gerek kalmaz.

Çoktan Seçmeli · LZW

Soru 28: RLE mi, LZW mi?

Aşağıdaki 18 karakterlik girdilerden hangisinde RLE girdiyi büyütürken LZW (a, b, c ile başlayan sözlük) kod sayısını yarıya indirir?

B: Ardışık tekrar yok; RLE "1a1b1c…" ile 36 karaktere çıkar. LZW tekrar eden "abc" parçalarını sözlüğe ekler ve 9 kod üretir (0 1 2 3 5 4 6 9 4). A, C ve D'de uzun koşular vardır; onlarda RLE çok etkilidir.

Klasik Soru · Karşılaştırma

Soru 29: Senaryoya Göre Algoritma

Her senaryo için dersteki dizgi eşleştirme algoritmalarından birini seçin ve gerekçesini yazın:
(a) Ağdan akan ve geri okunamayan veride, en kötü durumu sınırlı bir arama gerekiyor.
(b) Bir editörde uzun bir İngilizce metinde 12 harfli bir kelime aranıyor.
(c) Bir belgede aynı uzunlukta binlerce cümle (intihal kontrolü) aranıyor.

Cevabı göster
  • (a) KMP: metin işaretçisi asla geri gitmez (akışa uygun); en kötü durumda da O(n + m).
  • (b) Boyer-Moore / Horspool: uzun örüntü ve geniş alfabede kötü karakter kuralı neredeyse m karakter atlar; pratikte en hızlısı, en iyi O(n/m).
  • (c) Rabin-Karp: örüntü hash'leri bir kümeye konur, her pencere O(1)'de güncellenip kümede aranır; beklenen O(n + k · m).

Kaba kuvvet ön işleme istemez ve kısa örüntüde yeterlidir, ama en kötü durumu O(n · m)'dir.

Klasik Soru · Karşılaştırma

Soru 30: LZW Özel Durumu

A = 0, B = 1 sözlüğüyle "ABABABA" sıkıştırılınca çıktı 0 1 2 4 olur. Açıcı 4 kodunu okuduğunda bu kod sözlüğünde henüz yoktur. Neden böyle olur ve açıcı 4'ün karşılığını nasıl bulur?

Cevabı göster
kodyazılaneklenen
0A—
1B2 = AB
2AB3 = BA
4ABA4 = ABA

Açıcı sözlüğe bir adım geriden ekler: bir girdiyi ancak sonraki kodun ilk karakterini öğrenince tamamlar. Sıkıştırıcı 4 = "ABA"yı ekleyip hemen ardından kullandığında (cScSc kalıbı) açıcıda 4 henüz yoktur.

Bu durumda yazılacak dizgi w ile başlar ve ilk karakteri w[0]'dır: e = w + w[0] = "AB" + "A" = "ABA". Sonuç: A · B · AB · ABA = ABABABA ✓.

Son

Bölüm 5: Dizgi Algoritmaları: Çalışma Soruları
Konu anlatımı: Dizgi Algoritmaları sunumu · Terim sözlüğü
1 / 1 Sercan KÜLCÜ, Tüm hakları saklıdır.