Python 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 dengan 0 status keluar)
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 adalah variasi KMP, menggunakan tes berbasis indeks untuk pencocokan karakter. Ide dasarnya adalah bahwa jika kita mendapatkan ketidakcocokan pada posisi X[i]maka kita dapat kembali ke tempat yang memungkinkan untuk pertandingan sesuai dengan sufiks terpanjang X[:i]yaitu isomorfik ke awalan X.
Bekerja dari kiri ke kanan, kami menetapkan setiap karakter indeks yang sama dengan jarak ke kemunculan karakter sebelumnya, atau jika tidak ada kejadian sebelumnya maka kami mengambil panjang awalan string saat ini. Sebagai contoh:
MISSISSIPPI
12313213913
Untuk menguji apakah dua karakter cocok, kami membandingkan indeks, menyesuaikan dengan tepat untuk indeks yang lebih besar dari panjang string (sub) saat ini.
Algoritma KMP menjadi sedikit disederhanakan karena kita tidak bisa mendapatkan ketidakcocokan pada karakter pertama.
Program ini menghasilkan kecocokan pertama jika ada. Saya menggunakan kesalahan runtime untuk keluar jika terjadi kecocokan, tetapi kode dapat dengan mudah dimodifikasi untuk keluar dengan bersih dengan biaya beberapa byte.
Catatan: Untuk menghitung indeks, kita dapat menggunakan str.rfind(sebagai lawan dari pendekatan saya sebelumnya menggunakan kamus) dan masih memiliki kompleksitas linier, dengan asumsi bahwa str.rfindmulai mencari dari akhir (yang tampaknya satu-satunya pilihan implementasi yang waras) - untuk setiap karakter dalam alfabet , kita tidak perlu melewati bagian yang sama dari string dua kali, jadi ada batas atas (ukuran alfabet) * (ukuran string) perbandingan.
Karena kode menjadi agak kabur dalam permainan golf, berikut ini adalah solusi (293 byte) sebelumnya yang sedikit lebih mudah dibaca:
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!'
The etes fungsi ekivalensi karakter. The execpernyataan memberikan indeks dan melakukan beberapa initialisations variabel. Proses loop pertama Xuntuk nilai jatuh kembali, dan loop kedua melakukan pencarian string.
Pembaruan: Ini adalah versi yang keluar dengan bersih, dengan biaya satu byte:
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