Bu sorunu çözmek için olağan numaralandırma çalışmaz, çünkü asimptotikleri O(t*s) olacaktır. Bu nedenle, alt dizi arama görevleri için KMP (Knuth-Morris-Pratt) algoritması kullanılır.
Bu algoritmayı uygulamak için, dize ön eki işlevi kullanılır; bu, n (strong>s uzunluk) uzunluğundaki sayılardan oluşan bir dizidir; buradaki her öğe, maksimum uzunluktur s alt dizesinin en büyük kendi son ekinin ön ekiyle eşleşir. Örneğin:
Çizgi |
Önek işlevi |
Not |
abababcab |
0 0 1 2 3 4 0 1 2 |
|
abcabcd |
0 0 0 1 2 3 0 |
|
aabaaab |
0 1 0 1 2 2 3 |
|
O(n^3) asimptotikli önemsiz önek işlev algoritması:
vektör<int> önek_işlevi (dize s) {
int n = (int ) s.uzunluk();
vektör<int>pi(n);
için (int i=0; i<n; ++i)
için (int k=0; k<=i; ++k)
if (s.substr(0,k) == s .substr(i-k+1,k))
pi[i] = k;
dönüşpi;
}
Ve şimdi şu şekilde bir dizi için bir önek işlevi yapmamız gerekiyor: & nbsp; t + # + s; burada #, metinde olmadığı açıkça görülen bir sınırlayıcı karakterdir. Önek işlevinin karşılık gelen ayırıcı karakterden sonraki değerlerini inceleyerek, elde edilen değerin istenen alt dizenin uzunluğuna eşit olması durumunda oluşumunun bulunduğuna dikkat edilmelidir. Örneğin, "abababcab" ve istenen "abab" alt dizesi, önek işlevi şöyle olacaktır:
0 0 1 2 0 1 2 3 4 3 4 0 1 2 karşılık gelen dizgenin öğelerini ayrıştırmamız gerekiyor s:
1 2 3 4 3 4 0 1 2 - Değerin 4 olduğu iki durum vardır (4. ve 6.), yani. uzunluk t, sonuç olarak cevap yazılmalıdır: 4 - 4 (uzunluk t) & nbsp; = 0 ve 6 - 4 = 2. Bunların doğru cevaplar olduğu ve "abab" aslında "abababcab" 0 ve 2 konumlarında.
Problem
t
dizgisinin s
dizisindeki tüm oluşumlarını bulun.
Giriş
İlk satırda s
dizisi yazılır, ikinci satır t
dizisini içerir. Her iki dize de yalnızca İngilizce harflerden oluşur. Satır uzunlukları 1 ile 50.000 (dahil) arasında değişebilir.
Çıktı
Yanıtta,
t
dizgisinin
s
dizgisindeki tüm oluşumlarını artan sırada çıktılayın. Satır konumlarının numaralandırılması sıfırdan başlar.
Örnekler
# |
Girdi |
Çıktı |
şey>
1 |
abababcab
abab
|
0 2 |