파이썬 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 종료 상태)
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!'
이 알고리즘은 문자 일치에 대한 색인 기반 테스트를 사용하여 KMP의 변형입니다. 기본 아이디어는 위치에서 불일치가 X[i]
발생 X[:i]
하면 접두사 접두사와 동형 인 최장 접미사에 따라 일치하는 다음 장소로 넘어갈 수 있다는 것입니다 X
.
왼쪽에서 오른쪽으로 작업하면서 각 문자에 해당 문자의 가장 최근에 발생한 것과 거리가 같은 인덱스를 할당하거나 이전에 발생하지 않은 경우 현재 문자열 접두사의 길이를 사용합니다. 예를 들면 다음과 같습니다.
MISSISSIPPI
12313213913
두 문자가 일치하는지 테스트하기 위해 인덱스를 비교하여 현재 (하위) 문자열의 길이보다 큰 인덱스를 적절히 조정합니다.
첫 번째 문자에서 불일치를 얻을 수 없으므로 KMP 알고리즘이 약간 단순화됩니다.
이 프로그램은 첫 번째 일치 항목이 있으면 출력합니다. 일치하는 경우 런타임 오류를 사용하여 종료하지만 일부 바이트 비용으로 깨끗하게 종료되도록 코드를 쉽게 수정할 수 있습니다.
참고 : 컴퓨팅 인덱스의 str.rfind
경우 사전을 사용하는 이전의 접근 방식과 달리 사용할 수 str.rfind
있으며 알파벳의 각 문자에 대해 끝에서 검색 을 시작 한다고 가정 할 때 (정확한 구현 선택으로 보입니다) 가정하면 선형 복잡도를 가질 수 있습니다 문자열의 같은 부분을 두 번 횡단 할 필요가 없으므로 (알파벳 크기) * (문자열 크기) 비교의 상한이 있습니다.
골프를 치르는 동안 코드가 난독 화되었으므로 조금 더 읽기 쉬운 이전 (293 바이트) 솔루션이 있습니다.
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!'
이 e
기능은 문자의 동등성을 테스트합니다. exec
문은 인덱스를 할당하고 몇 가지 변수 초기화를 해주고 않습니다. 첫 번째 루프 X
는 폴백 값을 처리 하고 두 번째 루프는 문자열 검색을 수행합니다.
업데이트 : 다음은 1 바이트의 비용으로 깨끗하게 종료되는 버전입니다.
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