Knuth-Morris-Pratt algorithm은 문자열에서 부분 문자열의 첫 번째 (그리고 아마도 다음) 어커런스를 찾는 것을 목표로합니다. 하위 문자열은 반복되는 부분을 포함 할 수 있으므로 어떤 종류의 역 추적 메커니즘을 사용합니다. 이것은 의사 코드의 알고리즘입니다 :크 누스 - 모리스 - 프랫 알고리즘의 중복 명령어
let m ← 0, i ← 0
while m + i < length(S) do
if W[i] = S[m + i] then
if i = length(W) - 1 then
return m
let i ← i + 1
else
if T[i] > -1 then
let m ← m + i - T[i], i ← T[i]
else
let i ← 0, m ← m + 1
(위키 백과에서 제공). W
부분 문자열과 S
검색 할 문자열 (모두 0부터 시작 함).
내가 알고리즘의 마지막 if
절에 대한 질문이 : if T[i] > -1 then
의 T
- 벡터 건설 알고리즘에 기반을, T[i]
인덱스 i = 0
에 0보다 작은임을에서만 가능 보인다. 이 경우 인덱스에서 더 빠른 "확인"을 수행 할 수 있습니다. 배열 액세스는 추가 명령입니다 (특히 캐시 오류을 고려한 경우). i ← 0
과 동일합니다.
T
의 구조는 다음과 같은 알고리즘에 의해 수행됩니다
let pos ← 2, cmd ← 0
let T[0] ← -1, T[1] ← 0
while pos < length(W) do
if W[pos-1] = W[cnd] then
let cnd ← cnd + 1, T[pos] ← cnd, pos ← pos + 1
else if cnd > 0 then // (*)
let cnd ← T[cnd]
else
let T[pos] ← 0, pos ← pos + 1
(위키 백과).
이제는 알고리즘이 0
또는 cnd
에서 T
으로 기록됩니다. 첫 번째 유형의 과제의 경우 진술은 사실입니다. 두 번째 경우에는 cmd
값에 따라 다릅니다.
이제는 cmd
을 줄일 수있는 유일한 방법은 두 번째 경우 (*)
입니다.이 경우 cmd는 값이 0 이하가 될 때까지 작고 작아집니다. 그러나 cmd
은 배열의 이미 초기화 된 부분에서 값을 취하므로 0
또는 -1
이 될 수 있습니다. cmd
이 실제로 -1
인 경우 값을 설정하기 전에 증가가 있기 때문에 은 0
으로 설정됩니다. cmd
이 0 일 경우 아무런 문제가 없습니다.
A는보다 효율적인 알고리즘이 이렇게 될 것이다 비트 :
let m ← 0, i ← 0
while m + i < length(S) do
if W[i] = S[m + i] then
if i = length(W) - 1 then
return m
let i ← i + 1
else
if i > 0 then
let m ← m + i - T[i], i ← T[i]
else
let m ← m + 1
이 문 맞습니까? 그렇지 않다면, 배열에 두 개 이상의 -1
이 나타나는 부분 문자열을 줄 수 있습니까?
불필요 * 비효율적 * 참조? – EJP