diff template library

Post on 30-Jun-2015

4.741 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

diff template libraryTatsuhiko Kubo

http://d.hatena.ne.jp/cubicdaiya

自己紹介

・名前 : 久保 達彦・ HatenaID:cubicdaiya・ twitter:@cubicdaiya・ HP:http://cccis.jp・職業 : プログラマ,時々サーバ管理者

diff template libraryとは

•拙作の diff ライブラリ (C++)

•略して dtl

•由来は C++ の STL(Standard Template Library

dtl-cpphttp://code.google.com/p/dtl-cpp/

dtl という名前は既に使われていたので、この名前に (_ _)

プロジェクトページ

今日の朝、最新版(1.08) をリリースしま

した。

dtl の特徴 (1)

•任意の型を持つ二つの要素列の差分が計算できる

•Unified Format が扱える

•C++ プログラムから diff3 が使える

•C++ プログラムから patch が使える

dtl の特徴 (2)

•修正 BSD ライセンス

•ヘッダファイルのみで構成

•他のライブラリには極力依存しない

•64bit 対応済

•生のポインタ使ってます

とりあえず使ってみよう

二つの文字列の差分を取る

二つの int 型配列の差分を取る

template によって要素と要素列という形で抽象化されるので、

いろんな場面で活用できる

・文字列 ( 文字の列 )・ int 型の配列 ( 数値の列 )・テキストファイル ( 文字列から成る行の列 )・ etc

三つの文字列をマージする

変更箇所が衝突した場合

patch

dtl の内部構造

そもそも Diff とは?

•Difference( 違い、差分 )

•複数のファイル間の差分を取るプログラム

Diff を取るというのは、

•Levenshtein Distance( 編集距離 )

•LCS(Long Common Subsequence)

•SES(Short Edit Script)

↑ の 3 つを求めることと同義

A から B への変換を実現するための要素の追加と削除の合計回数

2 つの要素列を A と B とするabcdef → acbedf C a D b C c D d A b C e A d C f

C: 共通 , D: 削除 , A: 追加

Levenstein Distance = A(n) + D(n) = 4

A(n) = 2, D(n) =2

Levenstein Distance

2 つの要素列を A と B とするabcdef → acbedf C a D b C c D d A b C e A d C f

C: 共通 , D: 削除 , A: 追加 LCS = (C a) + (C c) + (C e) + (C f) = acef

LCS

A と B の最長共通部分列

2 つの要素列を A と B とするabcdef → acbedf C a D b C c D d A b C e A d C f

C: 共通 , D: 削除 , A: 追加

SES

これ

A から B への変換を最小の編集回数で行うための手順

エディットグラフ

エディットグラフ

a

b

c

d

e

f

d a c f e a(0, 0)

(M, N)

x 軸

y 軸

•y 軸方向に +1 進む (SES の「追加」 )

•x 軸方向に +1 進む (SES の「削除」 )

• y 軸と x 軸の対角線上に進む (SES の「共通」 )

• 「共通」の場合のコストは 0 、それ以外は 1

Diff とは

a

b

c

d

e

f

d a c f e a(0, 0)

(M, N)

x 軸

y 軸

エディットグラフ上の点 (0, 0) から点 (M, N) (M=6, N=6) までの最短経路を求める問題

コスト = 編集距離

色んな Diff アルゴリズム

•動的計画法

•Myers のアルゴリズム

•Wu のアルゴリズム

•Gestalt Approach

差分の計算はかなり重い処理なので効率的なアルゴリズムが必要

dtl における差分の求め方

Wu のアルゴリズムを活用

•SES における削除回数 P に注目

•エディットグラフにおける座標 (M, N)までの最短経路を P=0 から 1 ずつ増やしていって探索する

•平均計算量は O(N+PD)

•最悪でも O(NP)

D = Δ + 2P

•二つの要素列の長さをそれぞれ M, N とする

•Δ = N - M (N >= M)

•D は編集距離

•P は SES における「削除」の合計数

Δ = D

a

b

c

a b c d e f

(3, 6)

a(0, 0)

Δ = 3

Δ ≠ D

a

b

c

d

q q a b e f(0, 0)

(4, 6)D=Δ の対角線からはみ出たらはみ出た分だけ戻ってこないといけない

P

Δ

P

D=Δ+2P により、探索範囲は以下のようになる

(0, 0)

(M, N)

P

Δ P

ここまでが探索範囲

探索の仕方

•fp(k, p) : P=p の時点で対角線k上における到達可能な最遠点

•snake(k ,y) : P=p の時点で任意の点(x, y) から到達可能な最遠点の y 座標を計算する関数

•k = y - x, p の初期値は 0 で 1 ずつ増やしていく

•fp(k, p)=N の時点での p が SES の削除回数 P

対角線 k = y - x

p(p, 0)

k = -p

k= Δ

k= Δ+p

(0, 0)

(M, N)x

y

Wu のアルゴリズムの実装例http://github.com/cubicdaiya/onp

その他の機能の実装についてちょこっと紹介

diff3 の実装

dtl のマージ手順

1. 要素列 B と A の差分を取る (SES を SES_BA とする )2. 要素列 B と C の差分を取る (SES を SES_BC とする )3. SES_BA と SES_BC を先頭から比較していき、A と C の変更点が組み合わされた要素列 S を生成する

patch の実装

patch は SES を使えば簡単

擬似コードです

•google-diff-match-patch

•LibXDiff(Git で使われている )

その他の diff ライブラリ

参考文献

•S.W.Maner, G.Myers, W.Miller, "An O(NP) Sequence Comparison Algorithm"

最後に

もし C++ で diff したくなったり、必要になったら是非使ってみてください。

バグレポートやパッチも大歓迎↓

http://code.google.com/p/dtl-cpp

cubicdaiya@gmail.com

ご静聴ありがとうございました

top related