[1]E.W.Myers, "An O(ND) difference algorithm and its variations", Algorithmixa, 1 (1986), pp.251-266 に論文を日本語に訳したものが載っており、参考になりました。
http://hp.vector.co.jp/authors/VA007799/viviProg/doc5.htm
上記の論文中のコードは「SED Shotest Edit Distance」の値を求めるだけで、
Diffの結果をどう組み立て格納していくかについてと、fpという配列の初期値を
何で埋めればよいのかが分からず、 かなり苦労しました。
アルゴリズムは上記のO(NP)そのままですが、javascriptで実装していく中で、
メイン処理とした親関数内でのループの部分はかなりすっきりさせ、
snakeへのパラメータは整数kを1つだけとする、snakeは値を返さない、等、
サンプルコードの原形はほとんどなくなってしまった感じです。
また、O(NP)はarr1.lengthがarr2.length以下であることが前提なのですが、
最初の段階でパラメータをチェックし、arr1.lengthがarr2.lengthより大きければ、
順番をひっくり返して、自分自身を呼ぶことにより、前提を満たすようにしました。
動くサンプルページ http://www123.ddo.jp/tools/diff.html
//@license http://www.opensource.org/licenses/mit-license.html MIT License //@author Mashiki //@see http://hp.vector.co.jp/authors/VA007799/viviProg/doc5.htm function diff(arr1, arr2, rev) { var len1=arr1.length, len2=arr2.length; // len1 <= len2でなければひっくり返す if (!rev && len1>len2) return diff(arr2, arr1, true); // 変数宣言及び配列初期化 var k, p, offset=len1+1, delta =len2-len1, fp=[], ed=[]; for (p=0; p<len1+len2+3; ++p) { fp[p] = -1; ed[p] = []; } // メインの処理 for (p=0; fp[delta + offset] != len2; p++) { for(k = -p ; k < delta; ++k) snake(k); for(k = delta + p; k >= delta; --k) snake(k); } return ed[delta + offset]; // snake function snake(k) { var x, y, e0, o, y1=fp[k-1+offset], y2=fp[k+1+offset]; if (y1>=y2) { // 経路選択 y = y1+1; x = y-k; e0 = ed[k-1+offset]; o = {edit:rev?'-':'+',arr:arr2, line:y-1} } else { y = y2; x = y-k; e0 = ed[k+1+offset]; o = {edit:rev?'+':'-',arr:arr1, line:x-1} } // 選択した経路を保存 if (o.line>=0) ed[k+offset] = e0.concat(o); var max = len1-x>len2-y?len1-x:len2-y; for (var i=0; i<max && arr1[x+i]===arr2[y+i]; ++i) { // 経路追加 ed[k+offset].push({edit:'=', arr:arr1, line:x+i}); } fp[k + offset] = y+i; } }
このコードを使わせていただきたいのですが、ライセンスは何になるでしょうか。MIT LicenseやCCあたりだとありがたいです。
返信削除またもしよろしければ、node.js用のライブラリにしたいのですが、よろしいでしょうか。
論文以外に元となるコードはありませんので、 どのようにお使いいただいても結構です。
返信削除ライセンスはMITが都合良ければMITということにします。
遅れましたが、対応ありがとうございます。
返信削除node.js用のライブラリを作成できたら、改めてお知らせします。