zoukankan      html  css  js  c++  java
  • 编辑距离(C++)

    给定两个字符串s1和s2,计算出将s1转换成s2所用的最少操作数。可以对一个字符串进行如下三种操作:1.插入一个字符;2.删除一个字符;3.替换一个字符。

    递归法的解题方式:
    两个字符串从后(i=s1.length()-1,j=s2.length()-1)往前比较,递归三要素之一——终止条件base case:i=-1或j=-1结束;递归三要素之二——终止时的处理:返回另一个字符剩下的长度。即base case是i走完s1或j走完s2,可以直接返回另一个字符串剩下的长度,这是因为当i走完s1,j没走完s2时,用插入操作把s2剩下的字符插入s1,需要j+1步(因为j从0开始);而当j走完s2而i没走完s1时,用删除操作把s1前面没处理的字符删掉,需要i+1步(因为j从0开始)。
    递归要素之三————提取重复逻辑。当比较的两个字符相同时,两字符串都向前搜索;而两个字符不同时,判断插入、删除、替换后哪个步骤最少,就从选那条路径。不能理解的读者可以看以前的一篇博文适合新手的递归理解。插入、删除、替换是怎么操作的可以看下列代码及注释。

    int dp(string s1, string s2, int i, int j)
    {
    	//i走完s1,j没走完s2,用插入操作把s2剩下的字符插入s1,需要j+1步(因为j从0开始)
    	if (i == -1)
    		return j + 1;
    	//j走完s2而i没走完s1,用删除操作把s1前面没处理的字符删掉,需要i+1步(因为j从0开始)
    	if (j == -1)
    		return i + 1;
    	//两个字符相同,直接往前移动i,j即可
    	if (s1[i] == s2[j])
    		return dp(s1, s2, i - 1, j - 1);
    	else
    		//插入:i不往前移,j往前移,说明只处理了s2,这是往s1中插入一个字符导致的。处理步骤+1。
    		//删除:i往前移,j不往前移,说明s1处理了一个字符而s2没处理,这是s1中删除了一个字符。处理步骤+1。
    		//替换:i往前移,j往前移,说明既处理了s1,也处理了s2,是为替换字符。处理步骤+1。
    		//递归步骤最少的那种(即把其他两种步骤多的排除了)。
    		return min(min(dp(s1, s2, i, j - 1) + 1, dp(s1, s2, i - 1, j) + 1), dp(s1, s2, i - 1, j - 1) + 1);
    }
    

    动态规划代码:
    单纯的递归代码会有很多重复计算的步骤,画出树形结构就能直观看出,因此采用动态规划法,利用备忘录数组dp[][]来保存结果,
    动态规划代码首先遇到的问题是数组的初始值,当s2为空,那么s1的长度就是要删除的步骤数,即dp[i][0]=i;当s1为空,s2的长度就是s1要插入的步骤数,即dp[0][j]=j。然后自底向上求解,递归是自顶向下。

    int minDistance2(string s1, string s2)
    {
    	int m = s1.length();
    	int n = s2.length();
    	vector<vector<int>> dp(m + 1, vector<int>(n + 1));
    	for (int i = 1; i <= m; i++)//<=说明遍历的次数是m-1+1次,即字符串的长度
    	{
    		dp[i][0] = i;
    	}
    	for (int j = 1; j <= n; j++)
    	{
    		dp[0][j] = j;
    	}
    	for (int i = 1; i <= m; i++)
    	{
    		for (int j = 1; j <= n; j++)
    		{
    			//if (s1[i] == s2[j])//运行结果不对,因为第i个字符的索引为i-1
    			if (s1[i-1] == s2[j-1])
    			{
    				dp[i][j] = dp[i - 1][j - 1];//第i行j列的步骤数等于第i-1行j-1列,因为字符相同不需什么操作,所以不用+1
    			}
    			else
    			{
    				dp[i][j] = min(min(dp[i - 1][j]+1, dp[i][j - 1]+1), dp[i - 1][j - 1]+1);//+1表示经过了一次操作
    			}
    		}
    	}
    	return dp[m][n];
    }
    
  • 相关阅读:
    ASP.NET中的DataBinder.Eval用法
    jquery Ajax调用asmx和ashx代码示例三级联动
    项目中使用的架构
    asp.net(c#)上传图片到数据库
    asp.net(c#)从数据库里读取图片并显示到页面
    一款好的UI草图设计软件
    Windows Azure云平台(无须提供信用卡)[转]
    推荐8个超棒的学习 jQuery 的网站
    推荐两个界面原型设计工具GUIDesignStudio 和 Mockups For Desktop
    在VS2010上使用C#调用非托管C++生成的DLL文件(图文讲解)
  • 原文地址:https://www.cnblogs.com/jiangzhongzhiwei/p/13259784.html
Copyright © 2011-2022 走看看