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 0 mit Beendigungsstatus)
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!'
Der Algorithmus ist eine Variation von KMP und verwendet einen indexbasierten Test für die Zeichenübereinstimmung. Die Grundidee ist, dass wir, wenn wir eine Fehlpaarung an der Position erhalten, X[i]auf den nächstmöglichen Platz für eine Übereinstimmung zurückgreifen können, wobei das längste Suffix davon X[:i]isomorph zu einem Präfix von ist X.
Wenn Sie von links nach rechts arbeiten, weisen Sie jedem Zeichen einen Index zu, der dem Abstand zum letzten Vorkommen dieses Zeichens entspricht. Wenn es kein vorheriges Vorkommen gibt, nehmen Sie die Länge des aktuellen Zeichenfolgepräfix. Beispielsweise:
MISSISSIPPI
12313213913
Um zu testen, ob zwei Zeichen übereinstimmen, vergleichen wir Indizes und passen sie entsprechend an Indizes an, die länger als die aktuelle (Unter-) Zeichenfolge sind.
Der KMP-Algorithmus wird etwas vereinfacht, da beim ersten Zeichen keine Abweichung festgestellt werden kann.
Dieses Programm gibt die erste Übereinstimmung aus, falls eine vorhanden ist. Ich verwende einen Laufzeitfehler, um im Falle einer Übereinstimmung zu beenden, aber der Code kann leicht geändert werden, um auf Kosten einiger Bytes sauber zu beenden.
Hinweis: Für die Berechnung von Indizes können wir verwendenstr.rfind (im Gegensatz zu meinem früheren Ansatz mit einem Wörterbuch) eine lineare Komplexität verwenden und gehen davon aus, dass str.rfinddie Suche am Ende beginnt (was die einzig vernünftige Implementierungsoption zu sein scheint) - für jedes Zeichen im Alphabet Müssen wir nie denselben Teil der Zeichenkette zweimal durchlaufen, so gibt es eine Obergrenze für (Alphabetgröße) * (Zeichenkettengröße) Vergleiche.
Da der Code während des Golfspiels ziemlich verschleiert wurde, finden Sie hier eine frühere (293 Byte) Lösung, die etwas einfacher zu lesen ist:
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!'
Die eFunktion testet die Gleichwertigkeit von Zeichen. Die execAnweisung weist Indizes zu und führt einige Variableninitialisierungen durch. Die erste Schleife wird ausgeführtX die Fallback-Werte, und die zweite Schleife führt die Zeichenfolgensuche durch.
Update: Hier ist eine Version, die auf Kosten eines Bytes sauber beendet wird:
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