SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine(コードジン) DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

japan.internet.com翻訳記事

編集距離アルゴリズムを使って文字列を変換する

2つのドキュメントや文字列を比較して変更箇所を調べる方法

 リスト1に示すのは、StringEditDistanceプログラムで編集グラフの構築とノードの距離計算に使われているMakeEditGraph関数です。この関数はグラフの配列を作成し、左端の列と最上部の行を初期化します。次に、配列内を左から右に移動しながら他のノードの距離を記録します。

 リスト2に示すのは、結果の表示に使われているDisplayResultsルーチンです。このルーチンは、終了ノードから開始ノードに向かって編集グラフの最良の経路を逆方向にたどります。経由する各ノードで、ルーチンはそのノードに到達するときに行われた変更の種類(削除、挿入、または文字の維持)をチェックし、出力の先頭に適切な文字を追加します。図2を見ると分かるように、削除された文字は打ち消し線付きの赤色、挿入された文字は下線付きの青色、両方の文字列で共通する文字は黒色で表示されます。

リスト1 2つの文字列の編集グラフを記録する
<pre><code>
// Fill in the edit graph for two strings.
private Node[,] MakeEditGraph(string string1, string string2)
{
    // Make the edit graph array.
    int num_cols = string1.Length + 1;
    int num_rows = string2.Length + 1;
    Node[,] nodes = new Node[num_rows, num_cols];

    // Initialize the leftmost column.
    for (int r = 0; r < num_rows; r++)
    {
        nodes[r, 0].distance = r;
        nodes[r, 0].direction = Direction.FromAbove;
    }

    // Initialize the top row.
    for (int c = 0; c < num_cols; c++)
    {
        nodes[0, c].distance = c;
        nodes[0, c].direction = Direction.FromLeft;
    }

    // Fill in the rest of the array.
    char[] chars1 = string1.ToCharArray();
    char[] chars2 = string2.ToCharArray();
    for (int c = 1; c < num_cols; c++)
    {
        // Fill in column c.
        for (int r = 1; r < num_rows; r++)
        {
            // Fill in entry [r, c].
            // Check the three possible paths to here.
            int distance1 = nodes[r - 1, c].distance + 1;
            int distance2 = nodes[r, c - 1].distance + 1;
            int distance3 = int.MaxValue;
            if (chars1[c - 1] == chars2[r - 1])
            {
                // There is a diagonal link.
                distance3 = nodes[r - 1, c - 1].distance;
            }

            // See which is cheapest.
            if ((distance1 <= distance2) && (distance1 <= distance3))
            {
                // Come from above.
                nodes[r, c].distance = distance1;
                nodes[r, c].direction = Direction.FromAbove;
            }
            else if (distance2 <= distance3)
            {
                // Come from the left.
                nodes[r, c].distance = distance2;
                nodes[r, c].direction = Direction.FromLeft;
            }
            else
            {
                // Come from the diagonal.
                nodes[r, c].distance = distance3;
                nodes[r, c].direction = Direction.FromDiagonal;
            }
        }
    }
    
    // Display the graph's nodes (for debugging).
    //DumpArray(nodes);

    return nodes;
}
</pre></code>
リスト2 変更箇所を表示する
<pre><code>
// Display the changes.
private void DisplayResults(string string1, string string2, Node[,] nodes, RichTextBox rch)
{
    // Build a list of the moves from finish to start.
    int num_rows = nodes.GetUpperBound(0) + 1;
    int num_cols = nodes.GetUpperBound(1) + 1;
    int r = num_rows - 1;
    int c = num_cols - 1;

    // Make some fonts.
    Font normal_font = rch.Font;
    Font insert_font = new Font(rch.Font, FontStyle.Underline);
    Font delete_font = new Font(rch.Font, FontStyle.Strikeout);

    // Continue until we reach the upper left corner.
    rch.Clear();
    while ((r > 0) || (c > 0))
    {
        switch (nodes[r, c].direction)
        {
            case Direction.FromAbove:
                rch.Select(0, 0);
                rch.SelectedText = string2.Substring(r - 1, 1);
                rch.Select(0, 1);
                rch.SelectionFont = insert_font;
                rch.SelectionColor = Color.Blue;
                r--;
                break;
            case Direction.FromLeft:
                rch.Select(0, 0);
                rch.SelectedText = string1.Substring(c - 1, 1);
                rch.Select(0, 1);
                rch.SelectionFont = delete_font;
                rch.SelectionColor = Color.Red;
                c--;
                break;
            case Direction.FromDiagonal:
                rch.Select(0, 0);
                rch.SelectedText = string2.Substring(r - 1, 1);
                rch.Select(0, 1);
                rch.SelectionFont = normal_font;
                rch.SelectionColor = Color.Black;
                r--;
                c--;
                break;
        }
    }

    // Dispose of the fonts we created.
    insert_font.Dispose();
    delete_font.Dispose();
}
</pre></code>

次のページ
行単位でのファイルの比較

この記事は参考になりましたか?

japan.internet.com翻訳記事連載記事一覧

もっと読む

この記事の著者

japan.internet.com(ジャパンインターネットコム)

japan.internet.com は、1999年9月にオープンした、日本初のネットビジネス専門ニュースサイト。月間2億以上のページビューを誇る米国 Jupitermedia Corporation (Nasdaq: JUPM) のニュースサイト internet.comEarthWeb.com からの最新記事を日本語に翻訳して掲載するとともに、日本独自のネットビジネス関連記事やレポートを配信。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

Rod Stephens(Rod Stephens)

10冊以上の書籍と200点以上の雑誌記事の著者にしてコンサルタント。著作の大部分はVisual Basicに関するものである。これまで、修復ディスパッチ、燃料税トラッキング、プロフェッショナルなフットボールトレーニング、廃水処理、地図作成、チケット販売などの種々雑多なアプリケーションに従事してきた。彼のWebサイト「VB Helper」は、1か月に7百万以上のヒットを記録しており、Visual Basicプログラマ向けに3つのニューズレターと何千ものヒントや例を提供している。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/4801 2012/07/09 15:32

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー