Bölüm 5: Dizgi Algoritmaları (2)
Çıktı Sorusu · Sözlüksel Sıra
Soru 1: karsilastir Çıktısı
Dersteki karsilastir metoduyla şu üç çağrı ne döndürür? karsilastir("car", "cart"), karsilastir("Zebra", "apple"), karsilastir("kale", "kaba")
int karsilastir(String a, String b) { int n = Math.min(a.length(), b.length()); for (int k = 0; k < n; k++) { char x = a.charAt(k), y = b.charAt(k); if (x != y) return x - y; // ilk farklı karakter } return a.length() - b.length(); }
Cevabı göster
-1 -7 10
- "car" · "cart": ilk 3 karakter eşit, kısa olan tükendi → 3 − 4 = −1 (önek önce gelir).
- "Zebra" · "apple": 'Z' (90) − 'a' (97) = −7: büyük harfler küçüklerden önce gelir.
- "kale" · "kaba": 3. karakter 'l' (108) − 'b' (98) = 10 > 0 → "kaba" önce gelir.
Çoktan Seçmeli · Sözlüksel Sıra
Soru 2: Karakter Kodu Sırası
{"b2", "B10", "ab", "Ab", "a"} dizisi Arrays.sort (yani compareTo) ile sıralanınca sonuç hangisidir?
D: compareTo karakter kodlarını karşılaştırır: tüm büyük harfler (A = 65, B = 66) küçük harflerden (a = 97) önce gelir. "a", "ab"nin öneki olduğu için önce gelir. A ve C insan alfabesi gibi büyük/küçük harfi eşit sayar; bunun için Collator ya da compareToIgnoreCase gerekir.
Adım Adım Çalıştırma · Sözlüksel Sıra
Soru 3: sozlukselSirala İzleme
sozlukselSirala metodu {"kivi", "elma", "armut", "erik"} dizisini sıralarken kaç takas yapar?
n = 4. Her i konumuna, kalanların sözlükçe en küçüğü takaslarla getirilecek.
"kivi".compareTo("elma") > 0 ('k' > 'e') → takas: a[0] = "elma".
"elma".compareTo("armut") > 0 ('e' > 'a') → takas: a[0] = "armut".
"armut" < "erik" → takas yok.
"kivi".compareTo("elma") > 0 ('k' > 'e') → takas: a[1] = "elma".
"elma" < "erik" → takas yok.
"kivi".compareTo("erik") > 0 ('k' > 'e') → takas: a[2] = "erik".
Sonuç: [armut, elma, erik, kivi]. 6 karşılaştırma, 4 takas; her compareTo en çok W karakter okur → O(N² · W).
void sozlukselSirala(String[] a) { int n = a.length; for (int i = 0; i < n - 1; i++) for (int j = i + 1; j < n; j++) if (a[i].compareTo(a[j]) > 0) { String gecici = a[i]; a[i] = a[j]; a[j] = gecici; } }
Çoktan Seçmeli · Sözlüksel Sıra
Soru 4: Sayılar Dizgi Olarak
{"10", "9", "100", "2", "25"} dizgileri sözlüksel sıraya konursa sonuç hangisidir?
B: Soldan karakter karşılaştırılır: '1' < '2' < '9'. "10", "100"ün önekidir, önce gelir; "2", "25"in önekidir. A sayısal sıradır; bunun için tam sayıya çevirmek ya da sıfırla aynı uzunluğa getirmek ("002", "009", "010"…) gerekir.
Çıktı Sorusu · Basamak Sıralaması
Soru 5: LSD Geçişleri
[503, 87, 512, 61, 908, 170, 897, 275] dizisine LSD basamak sıralaması uygulanıyor (her geçiş kararlı saymalı sıralama). Her geçişten sonraki diziyi yazın.
Cevabı göster
| geçiş | anahtar | dizi |
|---|---|---|
| 1 | birler | 170, 61, 512, 503, 275, 87, 897, 908 |
| 2 | onlar | 503, 908, 512, 61, 170, 275, 87, 897 |
| 3 | yüzler | 61, 87, 170, 275, 503, 512, 897, 908 |
1. geçişte 503 ve 275 kararlılık sayesinde (3 < 5) değil, birler basamağına göre yerleşir; 897 ile 87 aynı anahtarı (7) taşır ve giriş sırasını (87 önce) korur. 2. geçişte 503 ve 908 (onlar = 0) önceki sırayı korur. 87 ve 61 yüzler basamağında 0 kabul edilir.
Adım Adım Çalıştırma · Basamak Sıralaması
Soru 6: sayarakSirala İzleme
a = {"cab", "bad", "ace", "dab", "bed", "add"} için sayarakSirala(a, 1) çağrısından sonra a ne olur?
d = 1 (2. karakter). Anahtarlar: a, a, c, a, e, d. Sayma: say[a] = 3, say[c] = say[d] = say[e] = 1.
Önek toplamı: say[c] artık c kovasının bittiği konum: a → 3, b → 3, c → 4, d → 5, e → 6.
i = 5: "add", anahtar 'd' → say[d] bir azalır, gec[4] = "add".
i = 4: "bed", anahtar 'e' → say[e] bir azalır, gec[5] = "bed".
i = 3: "dab", anahtar 'a' → say[a] bir azalır, gec[2] = "dab".
i = 2: "ace", anahtar 'c' → say[c] bir azalır, gec[3] = "ace".
i = 1: "bad", anahtar 'a' → say[a] bir azalır, gec[1] = "bad".
i = 0: "cab", anahtar 'a' → say[a] bir azalır, gec[0] = "cab".
Sonuç: cab, bad, dab, ace, add, bed. Anahtarı a olan cab, bad, dab giriş sırasını korudu (kararlı); sondan başa yerleştirme bunu sağlar.
void sayarakSirala(String[] a, int d) { int[] say = new int[256]; // ASCII for (String s : a) say[kar(s, d)]++; for (int r = 1; r < 256; r++) say[r] += say[r - 1]; String[] gec = new String[a.length]; for (int i = a.length - 1; i >= 0; i--) gec[--say[kar(a[i], d)]] = a[i]; // kararlı System.arraycopy(gec, 0, a, 0, a.length); } int kar(String s, int d) { // kısa dizgi → 0 return d < s.length() ? s.charAt(d) : 0; }
Çoktan Seçmeli · Basamak Sıralaması
Soru 7: Ters Yönlü Yerleştirme
sayarakSirala metodunda yerleştirme döngüsü sondan başa yerine baştan sona (for (int i = 0; i < a.length; i++)) yazılırsa LSD basamak sıralaması ne olur?
A: say[c] kovanın sonunu gösterir; baştan gelen ilk öğe kovanın en sonuna yazılır, yani eşitler ters sıralanır (kararsız). LSD'nin doğruluğu, son geçişte eşit olan öğelerin önceki geçişlerin kurduğu sırayı korumasına dayanır; bu yüzden ilk geçişlerin işi bozulur.
Çoktan Seçmeli · Basamak Sıralaması
Soru 8: Karşılaştırmasız Sıralama
Dizinin öğelerini birbiriyle karşılaştırmadan sıralayan ve bu yüzden Ω(N log N) alt sınırına tabi olmayan algoritma hangisidir?
C: Basamak (radix) sıralaması anahtarları basamak/karakter olarak kovalara dağıtır; LSD O(W · (N + R)) sürer. Birleştirme, hızlı ve yığın sıralaması compareTo gibi karşılaştırmalara dayanır ve en az Ω(N log N) karşılaştırma yapar.
Çoktan Seçmeli · Basamak Sıralaması
Soru 9: LSD mi, MSD mi?
Hangi veri kümesi LSD basamak sıralaması için en uygun olanıdır?
B: Anahtarlar kısa ve sabit uzunluklu: W = 7 geçiş, her geçiş O(N + R) → toplam O(7 · (N + 256)). Uzunlukları çok farklı dizgilerde (A) W en uzun dizgiye göre belirlenir ve kısa dizgiler boşuna taranır; orada MSD ya da karşılaştırmalı sıralama tercih edilir.
Çoktan Seçmeli · Düzenli İfadeler
Soru 10: ab*c Örüntüsü
Pattern.compile("ab*c").matcher(s).find() aşağıdaki dizgilerden hangisi için false döner?
D: * yalnızca önündeki b'ye uygulanır: a, sıfır ya da daha çok b, sonra c. "ac" (sıfır b), "abbc" ve "xabcx" içinde böyle bir parça vardır (find dizginin bir parçasını arar). "adc"de a ile c arasında d olduğu için eşleşme yoktur.
Çıktı Sorusu · Düzenli İfadeler
Soru 11: find Döngüsü
Aşağıdaki kod ne yazdırır?
Pattern p = Pattern.compile("\\d+");
Matcher m = p.matcher("Oda 12, kat 3, no 45a");
while (m.find())
System.out.println(m.group()
+ " @" + m.start());Cevabı göster
12 @4 3 @12 45 @18
\d+ bir ya da daha çok ardışık rakamı açgözlü biçimde alır: "12" tek parça olarak eşleşir, "1" ve "2" ayrı değil. "45a" içindeki a rakam olmadığından eşleşme 45'te biter. start() eşleşmenin başladığı indistir. Java dizgisinde ters bölü iki kez yazılır: "\\d+".
Çıktı Sorusu · Düzenli İfadeler
Soru 12: matches ve find
Aşağıdaki kod ne yazdırır?
Pattern d = Pattern.compile("\\d+");
System.out.println("abc123".matches("\\d+"));
System.out.println(d.matcher("abc123").find());
System.out.println("2024".matches("\\d{4}"));
System.out.println("20245".matches("\\d{4}"));
String r = "[A-Z]{2}\\d{3}";
System.out.println("AB123".matches(r));
System.out.println("ab123".matches(r));Cevabı göster
false true true false true false
matchesdizginin tamamını eşleştirmeye çalışır (örtük ^…$): "abc123" baştan rakamla başlamaz → false.findbir parçayı arar: "123" bulunur → true.- \d{4} tam dört rakam: "2024" true, "20245" false (beşinci rakam artar).
- [A-Z] yalnızca büyük harf: "ab123" false.
Çoktan Seçmeli · Düzenli İfadeler
Soru 13: İleri Bakış
a(?=b) örüntüsü "abacab" dizgisinde find() ile kaç kez eşleşir ve her eşleşme hangi metindir?
C: ileri bakış bir konumu sınar, karakter tüketmez: ardından b gelen a'lar 0 ve 4 konumlarındadır; 2. konumdaki a'dan sonra c gelir. Eşleşme yalnızca "a"dır, b eşleşmeye katılmaz (A bu yüzden yanlıştır).
Çoktan Seçmeli · Düzenli İfadeler
Soru 14: Açgözlü ve Tembel
"<b>x</b>" metninde <.+> ve <.+?> örüntülerinin ilk find() sonucu (group()) sırasıyla nedir?
B: .+ açgözlüdür, mümkün olan en uzun parçayı alıp son >'ye kadar gider. +? tembeldir, ilk >'de durur. Eşleşme her zaman en soldaki uygun konumdan (0) başlar; bu yüzden C'deki </b> ilk sonuç olamaz.
Çoktan Seçmeli · Düzenli İfadeler
Soru 15: \w ve Türkçe
Java'da "şeker".matches("\\w+") ne döndürür?
B: Java'da \w varsayılan olarak [a-zA-Z0-9_]'dir; ş bu kümede yoktur ve matches tüm dizgiyi istediği için false döner. Türkçe harfler için \p{L} ya da Pattern.UNICODE_CHARACTER_CLASS kullanılır.
Adım Adım Çalıştırma · Sonlu Durum Makineleri
Soru 16: DFA Çalıştırma
Derste verilen DFA (A başlangıç, D kabul) kabulEder(gecis, kabul, "1011010") çağrısında hangi durumlardan geçer, sonuç nedir?
Başlangıç durumu A (0). Geçiş tablosu: her (durum, sembol) için tek hedef; yalnızca D kabul durumudur.
1. sembol 1: δ(A, 1) = B.
2. sembol 0: δ(B, 0) = B.
3. sembol 1: δ(B, 1) = C.
4. sembol 1: δ(C, 1) = D. D kabul durumu ama girdi bitmedi.
5. sembol 0: δ(D, 0) = D. D kabul durumu ama girdi bitmedi.
6. sembol 1: δ(D, 1) = A.
7. sembol 0: δ(A, 0) = E.
Girdi bitti; son durum E kabul durumu değil → false (ret). Ara durumda D'den geçmek yetmez; yalnızca son durum önemlidir.
boolean kabulEder(int[][] gecis, boolean[] kabul, String s) { int durum = 0; // başlangıç for (char c : s.toCharArray()) durum = gecis[durum][c - '0']; return kabul[durum]; // kabul mü? }
Çıktı Sorusu · Sonlu Durum Makineleri
Soru 17: Sayı Ayrıştıran FSM
Dersteki sayilariBul metodu sayilariBul("v1.2.3 ve 7") çağrısında ne yazdırır?
void sayilariBul(String s) { Durum d = Durum.BASLA; StringBuilder tampon = new StringBuilder(); for (char c : s.toCharArray()) { boolean rakam = Character.isDigit(c); if (rakam) { if (d == Durum.BASLA) d = Durum.RAKAM; tampon.append(c); } else if (c == '.' && d != Durum.ONDALIK) { d = Durum.ONDALIK; tampon.append(c); } else if (d != Durum.BASLA) { System.out.println(tampon); tampon.setLength(0); d = Durum.BASLA; } } if (d != Durum.BASLA) System.out.println(tampon); }
Cevabı göster
1.2 3 7
- "1" → RAKAM, "." → ONDALIK, "2" → tampon "1.2".
- İkinci "." geldiğinde d zaten ONDALIK: ikinci koşul tutmaz, üçüncü dal çalışır → "1.2" yazılır, BASLA'ya dönülür; nokta atılır.
- "3" yeni sayı; boşlukta yazılır. "7" girdi sonunda son satırdaki if ile yazılır.
Makine "1.2.3" gibi bir sürüm numarasını iki sayıya böler; bu, durum tasarımının sonucudur.
Çoktan Seçmeli · Sonlu Durum Makineleri
Soru 18: NFA'dan DFA'ya
n durumlu bir NFA, alt küme kurulumuyla (subset construction) DFA'ya çevriliyor. Elde edilen DFA'nın durum sayısı en kötü durumda kaçtır?
C: DFA'nın her durumu NFA durumlarının bir alt kümesidir; n elemanlı kümenin 2ⁿ alt kümesi vardır. NFA, DFA ve düzenli ifade aynı dilleri tanır; fark durum sayısı ve çalıştırma kolaylığıdır (DFA'da her sembolde tek tablo okuması, O(n)).
Çoktan Seçmeli · Sonlu Durum Makineleri
Soru 19: Örüntü Otomatı
"abab" örüntüsünü arayan otomatta durum q = metnin sonunda örüntüyle uyuşan en uzun önekin uzunluğudur. Otomat 0 durumundan başlayıp "abaa" metnini okuyunca hangi durumdadır?
B: Durumlar: a → 1, b → 2, a → 3; dördüncü karakter a, beklenen b değil. "abaa"nın "abab" öneki olan en uzun soneki "a"dır → q = 1 (0'a düşmez). Bu geri dönüş KMP'deki önek fonksiyonunun otomat biçimidir.
Adım Adım Çalıştırma · Düzenleme Uzaklığı
Soru 20: levenshtein İzleme
levenshtein("ELMA", "ALEM") tablosu satır satır nasıl dolar, sonuç nedir?
5 × 5 tablo. İlk sütun D[i][0] = i (i silme), ilk satır D[0][j] = j (j ekleme). Diğer hücreler henüz 0.
1. satır (E): 1, 2, 2, 3. E = E olan hücrede (j = 3) maliyet eklenmez: D[1][3] = D[0][2] = 2 (yeşil).
2. satır (L): 2, 1, 2, 3. L = L olan hücrede (j = 2) maliyet eklenmez: D[2][2] = D[1][1] = 1 (yeşil).
3. satır (M): 3, 2, 2, 2. M = M olan hücrede (j = 4) maliyet eklenmez: D[3][4] = D[2][3] = 2 (yeşil).
4. satır (A): 3, 3, 3, 3. A = A olan hücrede (j = 1) maliyet eklenmez: D[4][1] = D[3][0] = 3 (yeşil).
D[4][4] = 3. Bir çözüm: üç değiştirme E→A, M→E, A→M (ELMA → ALMA → ALEA → ALEM). Zaman O(m · n).
int levenshtein(String a, String b) { int m = a.length(), n = b.length(); int[][] D = new int[m + 1][n + 1]; for (int i = 0; i <= m; i++) D[i][0] = i; for (int j = 0; j <= n; j++) D[0][j] = j; for (int i = 1; i <= m; i++) for (int j = 1; j <= n; j++) if (a.charAt(i - 1) == b.charAt(j - 1)) D[i][j] = D[i - 1][j - 1]; // eşit else D[i][j] = 1 + Math.min(D[i - 1][j - 1], Math.min(D[i][j - 1], D[i - 1][j])); return D[m][n]; }
Çıktı Sorusu · Düzenleme Uzaklığı
Soru 21: Uzaklık Değerleri
Dersteki levenshtein metoduyla aşağıdaki kod ne yazdırır? Her biri için bir düzenleme dizisi verin.
String[][] c = {{"algoritma", "logaritma"},
{"pazar", "bazaar"}, {"abc", ""},
{"kitap", "kitap"}};
for (String[] p : c) {
int d = levenshtein(p[0], p[1]);
System.out.println(d);
}Cevabı göster
3 2 3 0
- algoritma → logaritma: baştaki a'yı sil (lgoritma), l'den sonra o ekle (logoritma), ikinci o→a değiştir (logaritma) → 3.
- pazar → bazaar: p→b değiştir, bir a ekle → 2.
- abc → "": 3 silme (ilk sütun D[3][0] = 3).
- Aynı dizgiler: 0 (metrik özelliği d(a, a) = 0).
Çoktan Seçmeli · Düzenleme Uzaklığı
Soru 22: Yer Değiştirme Bir İşlem mi?
levenshtein("saat", "asat") kaçtır?
B: İki komşu harfin yer değiştirmesi Levenshtein'da tek işlem değildir: s→a ve a→s iki değiştirme ya da bir silme ve bir ekleme gerekir → 2. Komşu takası tek işlem sayan ölçü Damerau-Levenshtein uzaklığıdır.
Çoktan Seçmeli · Düzenleme Uzaklığı
Soru 23: Yalnız Ekleme ve Silme
Yalnızca ekleme ve silmeye izin verilirse (değiştirme yok) "ELMA"yı "ALEM"e dönüştürmek için en az kaç işlem gerekir? (LCS("ELMA", "ALEM") = 2)
C: Uzaklık = m + n − 2 · LCS = 4 + 4 − 4 = 4: ortak alt dizi (ör. "LM") dışındaki 2 harf silinir, 2 harf eklenir. Değiştirmeye de izin veren Levenshtein bunu 3'e indirir (bkz. izleme sorusu).
Çıktı Sorusu · En Uzun Ortak Alt Dizi
Soru 24: lcs Çıktısı
Dersteki lcs metodu (geri okumada L[i−1][j] > L[i][j−1] ise yukarı, değilse sola gider) ile kod ne yazdırır?
System.out.println(lcs("XMJYAUZ", "MZJAWXU"));
System.out.println(lcs("ELMA", "ALEM"));
System.out.println(lcs("ABC", "DEF").length());Cevabı göster
MJAU LM 0
- XMJYAUZ · MZJAWXU: tablonun son hücresi 4; geri okuma M, J, A, U eşleşmelerini bulur.
- ELMA · ALEM: uzunluk 2; "EM" de bir LCS'dir, ama eşitlikte sola gidildiği için kod "LM"yi verir. LCS tek olmak zorunda değildir, uzunluğu tektir.
- Ortak karakter yok → boş dizgi, uzunluk 0.
Çoktan Seçmeli · En Uzun Ortak Alt Dizi
Soru 25: Alt Dizi ve Alt Dizgi
A = "GXTXAYB" için aşağıdakilerden hangisi doğrudur?
C: G, T, A, B sırayla 0, 2, 4, 6. konumlarda geçer: göreli sıra korunur → alt dizi; ama bitişik değillerdir → alt dizgi değil. Her alt dizgi aynı zamanda alt dizidir (B ve D bu yüzden yanlış); "XAY" konum 3, 4, 5'te bitişik geçer, ikisidir.
Çıktı Sorusu · Sonek Dizisi ve BWT
Soru 26: Sonek Dizisi
"kazak" dizgisinin sonek dizisini (SA) bulun. Sonra "ak" örüntüsünün metinde geçtiği konumları SA üzerinde ikili aramayla nasıl bulacağınızı açıklayın.
Cevabı göster
| sıra | SA | sonek |
|---|---|---|
| 0 | 3 | ak |
| 1 | 1 | azak |
| 2 | 4 | k |
| 3 | 0 | kazak |
| 4 | 2 | zak |
SA = [3, 1, 4, 0, 2]. "ak" ile başlayan sonekler sıralı listede bitişik bir aralık oluşturur: yalnızca sıra 0 ("ak") → konum 3. "a" ile başlayanlar sıra 0–1 (konum 3 ve 1). Aralığın iki ucu ikili aramayla O(m log n)'de bulunur.
Çıktı Sorusu · Sonek Dizisi ve BWT
Soru 27: BWT Hesabı
"ARABA" dizgisinin Burrows–Wheeler dönüşümünü (L sütunu) ve orijinal dizginin sıralı listedeki satır indisini bulun.
Cevabı göster
Döndürmeler: ARABA, RABAA, ABAAR, BAARA, AARAB → sıralı: AARAB, ABAAR, ARABA, BAARA, RABAA.
L = son sütun = BRAAA, satır indisi 2 (0'dan). Üç A yan yana toplandı; bu tekrarlar sonra Move-to-Front ve RLE ile iyi sıkışır. F sütunu (AAABR) L'nin sıralanmış hâlidir.
Adım Adım Çalıştırma · Sonek Dizisi ve BWT
Soru 28: Ters BWT İzleme
tersBWT("kyka$a") LF eşlemesiyle hangi metni geri üretir?
L = "kyka$a" (T = "kayak$"). sira[i]: L[i]'deki karakterin L'de kaçıncı kez geçtiği (0'dan).
F = sırala(L) = "$aakky". bas[c]: F'de c'nin ilk satırı: $ → 0, a → 1, k → 3, y → 5.
k = 0: L[0] = 'k' okunur; LF(0) = bas['k'] + sira[0] = 3 + 0 = 3.
k = 1: L[3] = 'a' okunur; LF(3) = bas['a'] + sira[3] = 1 + 0 = 1.
k = 2: L[1] = 'y' okunur; LF(1) = bas['y'] + sira[1] = 5 + 0 = 5.
k = 3: L[5] = 'a' okunur; LF(5) = bas['a'] + sira[5] = 1 + 1 = 2.
k = 4: L[2] = 'k' okunur; LF(2) = bas['k'] + sira[2] = 3 + 1 = 4.
Okunanlar metni sondan başa verir: "kayak" ters çevrilir → "kayak". Sıra sayılarıyla O(n).
String tersBWT(String L) { // $ en küçük
int n = L.length();
int[] say = new int[256], sira = new int[n];
for (int i = 0; i < n; i++)
sira[i] = say[L.charAt(i)]++;
int[] bas = new int[256]; // F'de ilk satır
for (int c = 1; c < 256; c++)
bas[c] = bas[c - 1] + say[c - 1];
StringBuilder s = new StringBuilder();
int i = 0; // $ satırı
for (int k = 0; k < n - 1; k++) {
char c = L.charAt(i);
s.append(c);
i = bas[c] + sira[i]; // LF(i)
}
return s.reverse().toString();
}Klasik Soru · Basamak Sıralaması
Soru 29: LSD Neden Sağdan Başlar?
LSD basamak sıralaması neden en sağdaki karakterden başlar ve neden her geçişin kararlı olması gerekir? 3 karakterlik dizgilerde k geçişten sonra dizinin hangi özelliği vardır?
Cevabı göster
- Değişmez: k geçişten sonra dizi, son k karaktere göre sıralıdır (ör. "dab", "cab" 1. geçişten sonra son harfe göre bir aradadır).
- Son geçiş en anlamlı karaktere göre yapılır; bu karakterde eşit olan öğelerin sırasına önceki geçişler karar vermiştir. Kararlılık bu kararı korur.
- Kararsız alt sıralama (ör. hızlı sıralama) eşitleri karıştırır; "bed" ile "bee" son geçişte yer değiştirebilir.
- W geçiş · O(N + R) → O(W · (N + R)); karşılaştırma yapılmaz.
MSD ise soldan başlar ve her kovayı ayrı ayrı özyinelemeli sıralar; ayırt edici önek bitince durabildiği için uzunlukları farklı dizgilere uygundur.