動態規劃-編輯距離

何畢之發表於2018-06-26
using System;
using System.Collections.Generic;

namespace 編輯距離
{
    class Program
    {
        public static readonly string str1 = "FAMILY";
        public static readonly string str2 = "FRAME";
        public static int[,] map = new int[str1.Length + 1, str2.Length + 1];

        static void Main(string[] args)
        {
            EditDistence();

            Console.WriteLine("行表示str1,列表示str2:");
            DisplayMap();

            Console.WriteLine();
            DisplayRes();

            Console.ReadKey();
        }

        /// <summary>  
        /// 編輯距離演算法  
        /// </summary>  
        static void EditDistence()
        {
            //初始化矩陣  第一行為0-str2的字串長度 第一列為0-str1的字串長度
            for (int i = 0; i < str1.Length + 1; i++)
                map[i, 0] = i;
            for (int j = 0; j < str2.Length + 1; j++)
                map[0, j] = j;

            for (int i = 1; i < str1.Length + 1; i++)
            {
                for (int j = 1; j < str2.Length + 1; j++)
                {
                    //若str1的第i個元素和str2的第j個元素相等 則map[i,j]等於 map中當前單元格左邊或者上面或左上較小的值
                    //若str1的第i個元素和str2的第j個元素不相等 則map[i,j]等於 map中當前單元格左邊或者上面或左上較小的值+1  
                    if (str1[i - 1] == str2[j - 1])
                        map[i, j] = Math.Min(Math.Min(map[i - 1, j], map[i, j - 1]), map[i - 1, j - 1]);
                    else
                        map[i, j] = Math.Min(Math.Min(map[i - 1, j], map[i, j - 1]), map[i - 1, j - 1]) + 1;
                }
            }
        }
        /// <summary>  
        /// 顯示編輯距離演算法運算後的MAP矩陣  
        /// </summary>  
        static void DisplayMap()
        {
            Console.Write("    ");
            for (int i = 0; i < str2.Length; i++)
            {
                Console.Write("  " + str2[i]);
            }
            Console.Write("\r\n");

            for (int i = 0; i < str1.Length + 1; i++)
            {
                if (i > 0 && i < str1.Length + 1)
                    Console.Write(str1[i - 1] + "  ");
                else
                    Console.Write("   ");
                for (int j = 0; j < str2.Length + 1; j++)
                {
                    Console.Write(map[i, j] + "  ");
                }
                Console.Write("\r\n");
            }
        }

        /// <summary>  
        /// 顯示編輯距離長度和編輯過程  
        /// </summary>  
        static void DisplayRes()
        {
            Console.WriteLine("str1和str2的編輯距離是:" + map[str1.Length, str2.Length]);
            Console.WriteLine("str1和str2的編輯距離的過程是:");

            List<string> process = new List<string>(); //用於存放過程

            int i = str1.Length, j = str2.Length;//分別表示MAP矩陣行和列 
            //逆序推測過程
            while (i > 0 && j > 0)
            {
                //若str1的第i個元素和str2的第j個元素不相等 則map[i,j]的元素來源於 上面、左側、左上的元素+1,若想等則取後者 同時定位到取值元素所在的位置
                //3鍾取值情況分別代表 刪除、插入、替換
                //若str1的第i個元素和str2的第j個元素相等 則取左上角元素繼續執行迴圈
                if (str1[i - 1] != str2[j - 1])
                {
                    if (map[i, j] == (map[i - 1, j - 1] + 1))
                    {
                        process.Add(str1[i - 1] + " 替換為 " + str2[j - 1]);
                        i--;
                        j--;
                        continue;
                    }
                    if (map[i, j] == (map[i - 1, j] + 1))
                    {
                        process.Add("刪除 " + str1[i - 1]);
                        i--;
                        continue;
                    }
                    if (map[i, j] == (map[i, j - 1] + 1))
                    {
                        process.Add("插入 " + str2[j - 1]);
                        j--;
                        continue;
                    }
                }
                else
                {
                    i--;
                    j--;
                }
            }

            for (int index = process.Count - 1; index > -1; index--)
                Console.WriteLine(process[index]);
        }
    }
}


相關文章