IT박스

차이 알고리즘?

itboxs 2020. 6. 2. 19:05
반응형

차이 알고리즘? [닫은]


작동하고 효율적인 diff 알고리즘에 대한 설명이 미친 것처럼 보였습니다.

내가 얻은 가장 가까운 것은 RFC 3284 (여러 Eric Sink 블로그 게시물에서)에 대한 링크 입니다. 이 링크 는 diff 결과가 저장되는 데이터 형식완벽하게 이해할 수있는 용어로 설명 합니다. 그러나 diff를 수행하는 동안 프로그램이 이러한 결과에 도달하는 방법에 대해서는 언급하지 않았습니다.

diff 알고리즘을 구현할 때 절충이 있어야한다고 확신하기 때문에 개인적 호기심에서 이것을 연구하려고합니다. diff 알고리즘을 볼 때 종종 분명하고 diff 프로그램이 왜 이것을 diff로 선택했는지 궁금합니다. 그것 대신에?"...

VCDIFF를 출력하는 효율적인 알고리즘에 대한 설명은 어디에서 찾을 수 있습니까?
그런데 SourceGear의 DiffMerge에서 사용하는 실제 알고리즘에 대한 설명을 찾으면 훨씬 좋습니다.

참고 : 가장 긴 공통 하위 시퀀스는 VCDIFF에서 사용하는 알고리즘이 아닌 것처럼 보입니다. 사용하는 데이터 형식에 따라 더 똑똑한 것으로 보입니다.


O (ND) 차이 알고리즘과 그 변형 은 훌륭한 논문이므로 여기서 시작할 수 있습니다. 여기에는 의사 코드와 diff 수행과 관련된 그래프 순회에 대한 멋진 시각화가 포함됩니다.

이 논문의 섹션 4 는 알고리즘을 개선하여 매우 효과적으로 개선하는 방법을 소개합니다.

이것을 성공적으로 구현하면 도구 상자에 매우 유용한 도구가 있습니다 (아마도 훌륭한 경험이 될 것입니다).

필요한 출력 형식을 생성하는 것은 때때로 까다로울 수 있지만 알고리즘 내부를 이해하고 있으면 필요한 것을 출력 할 수 있어야합니다. 휴리스틱을 도입하여 출력에 영향을 미치고 특정 상충 관계를 만들 수도 있습니다.

다음은 위에서 언급 한 알고리즘의 기술을 사용하여 약간의 문서, 전체 소스 코드 및 diff 알고리즘의 예 를 포함 하는 페이지 입니다 .

소스 코드가 밀접하게 기본 알고리즘을 따르도록 표시하고 읽기 쉽다.

입력 준비에 약간의 도움이 될 수도 있습니다. 문자 나 토큰 (단어)으로 구분할 때 출력에 큰 차이가 있습니다.

행운을 빕니다!


GNU에서 사용할 수 있는 diff 의 실제 소스 코드살펴 보는 것부터 시작하겠습니다 .

해당 소스 코드가 실제로 어떻게 작동하는지 이해하기 위해 해당 패키지의 문서는 소스 코드에서 영감을 얻은 논문을 참조합니다.

기본 알고리즘은 "O (ND) 차이 알고리즘 및 그 변형", Eugene W. Myers, 'Algorithmica'Vol. 1 No. 2, 1986, pp. 251-266; "파일 비교 프로그램"에서 Webb Miller와 Eugene W. Myers, 'Software--Practice and Experience'Vol. 15 No. 11, 1985, 1025-1040 쪽. 알고리즘은 "근사 문자열 매칭 알고리즘", E. Ukkonen,`Information and Control 'Vol. 64, 1985, 100-118 쪽.

논문을 읽고 구현을위한 소스 코드를 살펴보면 작동 방식을 이해하기에 충분해야합니다.


https://github.com/google/diff-match-patch를 참조 하십시오

"Diff Match 및 Patch 라이브러리는 일반 텍스트 동기화에 필요한 작업을 수행하는 강력한 알고리즘을 제공합니다. ... 현재 Java, JavaScript, C ++, C # 및 Python에서 사용 가능"

또한 wikipedia.org Diff 페이지 와 " Bram Cohen : diff 문제가 해결되었습니다 "를 참조하십시오.


diff 알고리즘을 찾고 여기에 와서 나만의 구현을했습니다. vcdiff에 대해 모르겠습니다.

위키 백과 : 가장 긴 공통 서브 시퀀스에서 diff-like 출력을 얻는 작은 단계 일뿐입니다. 서브 시퀀스에 항목이 없지만 원래 항목에 있으면 항목을 삭제해야합니다. (아래의 '–'표시) 하위 시퀀스에는 없지만 두 번째 시퀀스에있는 경우 추가해야합니다 ( '+'표시).

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가 제공 한 링크를 기반으로 Neil Fraser 웹 사이트 (도서관의 저자 중 하나) 에 Diff Strategies 가 많이 있습니다 .

그는 기본 전략을 다루고 기사 끝까지 Myer의 알고리즘과 일부 그래프 이론으로 진행합니다.

참고 URL : https://stackoverflow.com/questions/805626/diff-algorithm

반응형