Piton 2, 338 326 323 321 310 306 297 293 290 289 280 279 266 264 259 237 230 229 226 223 222 220 219 217 ( 260 238 231 228 225 223 221 220 218 0 çıkış durumu ile)
exec'''s=raw_input()
S=[M-s.rfind(c,0,M)for M,c in enumerate(s)]
k=0
j=x=%s
while k<=M+x:
if S[k]>j<W[j]or S[k]==W[j]:
k+=1;j+=1;T+=[j]
if j-L>x:print s[k-j:k];z
else:j=T[j]
'''*2%('-1;T=[0];W=S;L=M',0)
print'No!'
Algoritma, karakter eşleme için dizin tabanlı bir test kullanan bir KMP varyasyonudur. Temel fikir, eğer pozisyonda bir uyumsuzluk X[i]alırsak, o zaman X[:i]bir önek için izomorfik olan en uzun ekine göre bir maç için bir sonraki olası yere geri dönebiliriz X.
Soldan sağa doğru çalışarak, her karaktere o karakterin en son önceki oluşumuna olan mesafeye eşit bir dizin atarız veya daha önce bir oluşum yoksa, geçerli dize önekinin uzunluğunu alırız. Örneğin:
MISSISSIPPI
12313213913
İki karakterin eşleşip eşleşmediğini test etmek için, mevcut (alt) dizenin uzunluğundan daha büyük dizinler için uygun şekilde ayarlayarak dizinleri karşılaştırırız.
KMP algoritması biraz basitleşir, çünkü ilk karakterde uyumsuzluk elde edemeyiz.
Bu program varsa ilk eşleşmeyi çıkarır. Bir eşleşme durumunda çıkmak için bir çalışma zamanı hatası kullanıyorum, ancak kod kolayca bazı baytlar pahasına temiz çıkmak için değiştirilebilir.
Not: Hesaplama indeksleri için, str.rfind(sözlük kullanarak önceki yaklaşımımın aksine) ve str.rfindalfabetikteki her karakter için sondan aramaya başladığını varsayarak (tek aklı başında uygulama seçeneği gibi görünüyor ) hala doğrusal karmaşıklığa sahibiz. , asla dizenin aynı kısmını iki kez geçmemiz gerekmediği için (alfabe boyutu) * (dize boyutu) karşılaştırmalarının bir üst sınırı vardır.
Golf sırasında kod oldukça gizlendiğinden, okunması biraz daha kolay olan daha eski (293 bayt) bir çözüm var:
e=lambda a:a>i<W[i]or a==W[i]
exec('s=raw_input();S=[];p={};M=i=0\nfor c in s:S+=[M-p.get(c,-1)];p[c]=M;M+=1\nW=S;L=M;'*2)[:-9]
T=[0]*L
k=1
while~k+L:
if e(W[k]):i+=1;k+=1;T[k]=i
else:i=T[i]
m=i=0
while m+i<M:
if e(S[m+i]):
if~-L==i:print s[m:m+L];z
i+=1
else:m+=i-T[i];i=T[i]
print'No!'
eFonksiyon testleri karakterlerin eşitlik gösteren. execDeyim indeksleri atar ve bazı değişken alıştırmalarını yapar. İlk döngü Xgeri dönüş değerlerini işler ve ikinci döngü dize aramasını yapar.
Güncelleme: İşte bir bayt pahasına temiz bir şekilde çıkan bir sürüm:
r='No!'
exec'''s=raw_input()
S=[M-s.rfind(c,0,M)for M,c in enumerate(s)]
k=0
j=x=%s
while k<=M+x:
if S[k]>j<W[j]or S[k]==W[j]:
k+=1;j+=1;T+=[j]
if j-L>x:r=k=s[k-j:k]
else:j=T[j]
'''*2%('-1;T=[0];W=S;L=M',0)
print r