문제
나는 작동하고 효율적인 Diff 알고리즘에 대한 설명에 미친 것처럼 보였다.
내가 가장 가까운 것은입니다 이 RFC 3284에 대한 링크 완벽하게 이해할 수있는 용어로 설명하는 (여러 Eric 싱크 블로그 게시물) 데이터 형식 Diff 결과가 저장됩니다. 그러나 프로그램이 어떻게 이러한 결과에 도달 할 것인지에 대한 언급은 없습니다.
나는 Diff 알고리즘을 구현할 때 트레이드 오프가 있어야한다고 확신하기 때문에 개인적인 호기심에서 이것을 연구하려고 노력하고 있습니다. Diffs를 보았을 때 때때로 분명합니다. "Diff 프로그램이 왜 이것을 변화로 선택했는지 궁금해합니다. 그것 대신에?"...
VCDIFF를 출력하게되는 효율적인 알고리즘에 대한 설명은 어디에서 찾을 수 있습니까?
그건 그렇고, SourceGear의 Diffmerge가 사용하는 실제 알고리즘에 대한 설명을 찾으면 더 나을 것입니다.
참고 : 가장 긴 공통 후속은 VCDIFF에서 사용하는 알고리즘 인 것 같습니다. 그들이 사용하는 데이터 형식을 감안할 때 더 똑똑한 일을하는 것처럼 보입니다.
해결책
O (ND) 차이 알고리즘 및 변형 환상적인 종이이며 거기서 시작하고 싶을 수도 있습니다. 여기에는 의사 코드와 Diff 수행과 관련된 그래프 트래버스의 멋진 시각화가 포함됩니다.
섹션 4 이 논문은 알고리즘에 매우 효과적인 몇 가지 개선을 소개합니다.
이를 성공적으로 구현하면 도구 상자에 매우 유용한 도구가 생길 수 있습니다 (아마도 훌륭한 경험도있을 것입니다).
필요한 출력 형식을 생성하면 때때로 까다로울 수 있지만 알고리즘 내부를 이해하면 필요한 모든 것을 출력 할 수 있어야합니다. 또한 출력에 영향을 미치고 특정 트레이드 오프를하기 위해 휴리스틱을 소개 할 수도 있습니다.
여기에 페이지가 있습니다 여기에는 약간의 문서가 포함되어 있습니다. 전체 소스 코드, 앞서 언급 한 알고리즘의 기술을 사용한 Diff 알고리즘의 예.
그만큼 소스 코드 기본 알고리즘을 면밀히 따르는 것으로 보이며 읽기 쉽습니다.
입력을 준비하는 데 약간도 유용 할 수 있습니다. 문자 또는 토큰 (단어)별로 차이가있을 때 출력에는 큰 차이가 있습니다.
행운을 빕니다!
다른 팁
나는 실제를 보면서 시작할 것입니다 소스 코드 GNU가 만드는 Diff의 경우 사용 가능.
용을 위해 이해 해당 소스 코드가 실제로 어떻게 작동하는지에 대해 해당 패키지의 문서는 영감을 준 논문을 참조합니다.
기본 알고리즘은 "O (ND) 차이 알고리즘 및 그 변형", Eugene W. Myers, 'Algorithmica'Vol. 1 No. 2, 1986, 251-266 쪽; "파일 비교 프로그램"에서 Webb Miller와 Eugene W. Myers, '소프트웨어-연습 및 경험'Vol. 15 No. 11, 1985, pp. 1025-1040. 이 알고리즘은 "대략적인 문자열 일치에 대한 알고리즘", E. UKKONEN,`Information and Control 'Vol. 64, 1985, pp. 100-118.
논문을 읽은 다음 구현을위한 소스 코드를 살펴보면 작동 방식을 이해하기에 충분해야합니다.
보다 https://github.com/google/diff-match-patch
"Diff Match 및 Patch Libraries는 일반 텍스트 동기화에 필요한 작업을 수행하는 강력한 알고리즘을 제공합니다. 현재 Java, JavaScript, C ++, C# 및 Python에서 사용할 수 있습니다."
또한 참조하십시오 wikipedia.org diff 페이지 그리고 - "Bram Cohen : Diff 문제가 해결되었습니다"
나는 Diff 알고리즘을 찾아 여기에 와서 나중에 내 자신의 구현을했다. vcdiff에 대해 모른다.
위키 백과: 가장 긴 공통 후속에서는 차이와 같은 출력을 얻는 작은 단계 일뿐입니다. 항목이 후속에 없지만 원본에 존재하는 경우 삭제해야합니다. ( ' -'marks, 아래.) 후속에 없지만 두 번째 시퀀스에 존재하는 경우 ( '+'마크.) 추가되어야합니다.
멋진 애니메이션 LCS 알고리즘은 여기에 있습니다.
금식 링크 LCS 루비 구현.
느리고 간단한 루비 적응은 다음과 같습니다.
def lcs(xs, ys)
if xs.count > 0 and ys.count > 0
xe, *xb = xs
ye, *yb = ys
if xe == ye
return [xe] + lcs(xb, yb)
end
a = lcs(xs, yb)
b = lcs(xb, ys)
return (a.length > b.length) ? a : b
end
return []
end
def find_diffs(original, modified, subsequence)
result = []
while subsequence.length > 0
sfirst, *subsequence = subsequence
while modified.length > 0
mfirst, *modified = modified
break if mfirst == sfirst
result << "+#{mfirst}"
end
while original.length > 0
ofirst, *original = original
break if ofirst == sfirst
result << "-#{ofirst}"
end
result << "#{sfirst}"
end
while modified.length > 0
mfirst, *modified = modified
result << "+#{mfirst}"
end
while original.length > 0
ofirst, *original = original
result << "-#{ofirst}"
end
return result
end
def pretty_diff(original, modified)
subsequence = lcs(modified, original)
diffs = find_diffs(original, modified, subsequence)
puts 'ORIG [' + original.join(', ') + ']'
puts 'MODIFIED [' + modified.join(', ') + ']'
puts 'LCS [' + subsequence.join(', ') + ']'
puts 'DIFFS [' + diffs.join(', ') + ']'
end
pretty_diff("human".scan(/./), "chimpanzee".scan(/./))
# ORIG [h, u, m, a, n]
# MODIFIED [c, h, i, m, p, a, n, z, e, e]
# LCS [h, m, a, n]
# DIFFS [+c, h, +i, -u, m, +p, a, n, +z, +e, +e]
Emmelaich가 제공 한 링크를 바탕으로 Diff 전략이 많이 있습니다. Neil Fraser의 웹 사이트 (도서관의 저자 중 하나).
그는 기본 전략을 다루고 기사의 끝을 향해 Myer의 알고리즘과 일부 그래프 이론으로 진행됩니다.