编程之美--3.3

题目描述:计算相似度,其实本质就是计算编辑距离

思路:一开始先递归,然后加备忘改DP,发现有很多重复子问题,再重新设计dp算法

  1 #include <iostream>
  2 #include <queue>
  3 #include <climits>
  4 #include <algorithm>
  5 #include <memory.h>
  6 #include <stdio.h>
  7 using namespace std;
  8
  9
 10 int calSim_1(string s1,int b1,int e1,string s2,int b2,int e2)
 11 {
 12     if(b1 > e1)
 13     {
 14         if(b2 > e2)
 15         {
 16             return 0;
 17         }
 18         return e2 - b2 + 1;
 19     }
 20     if(b2 > e2)
 21     {
 22         if(b1 > e1)
 23         {
 24             return 0;
 25         }
 26         return e1 - b1 + 1;
 27     }
 28     if(s1[b1] == s2[b2])
 29     {
 30         return calSim_1(s1,b1+1,e1,s2,b2+1,e2);
 31     }
 32     else
 33     {
 34         int len1 = calSim_1(s1,b1,e1,s2,b2+1,e2);
 35         int len2 = calSim_1(s1,b1+1,e1,s2,b2,e2);
 36         int len3 = calSim_1(s1,b1+1,e1,s2,b2+1,e2);
 37
 38         len1 = min(len1,len2);
 39         len1 = min(len1,len3);
 40         return len1+1;
 41     }
 42 }
 43
 44 //递归+备忘录版本(DP)
 45 int opt[100][100];
 46 int calSim_2(string s1,int b1,int e1,string s2,int b2,int e2)
 47 {
 48     if(b1 > e1)
 49     {
 50         if(b2 > e2)
 51         {
 52             return 0;
 53         }
 54         return e2 - b2 + 1;
 55     }
 56     if(b2 > e2)
 57     {
 58         if(b1 > e1)
 59         {
 60             return 0;
 61         }
 62         return e1 - b1 + 1;
 63     }
 64     if(s1[b1] == s2[b2])
 65     {
 66         if(opt[b1+1][b2+1] == -1)
 67         {
 68             opt[b1+1][b2+1] = calSim_2(s1,b1+1,e1,s2,b2+1,e2);
 69         }
 70         return opt[b1+1][b2+1];
 71     }
 72     else
 73     {
 74         if(opt[b1][b2+1] == -1)
 75         {
 76             opt[b1][b2+1] = calSim_2(s1,b1,e1,s2,b2+1,e2);
 77         }
 78         int len1 = opt[b1][b2+1];
 79         if(opt[b1+1][b2] == -1)
 80         {
 81             opt[b1+1][b2] = calSim_2(s1,b1+1,e1,s2,b2,e2);
 82         }
 83         int len2 = opt[b1+1][b2];
 84         if(opt[b1+1][b2+1] == -1)
 85         {
 86             opt[b1+1][b2+1] = calSim_2(s1,b1+1,e1,s2,b2+1,e2);
 87         }
 88         int len3 = opt[b1+1][b2+1];
 89
 90         len1 = min(len1,len2);
 91         len1 = min(len1,len3);
 92         return len1+1;
 93     }
 94 }
 95
 96 //DP+非备忘录版本
 97 int dp[100][100];
 98 int calSim_3(string s1,string s2)
 99 {
100     int len1 = s1.length();
101     int len2 = s2.length();
102     int i,j;
103     for(i = 0 ; i <= s1.length() ; ++i)
104     {
105         dp[i][0] = i;
106     }
107     for(j = 0 ; j <= s2.length() ; ++j)
108     {
109         dp[0][j] = j;
110     }
111     for(i = 1 ; i <= s1.length() ; ++i)
112     {
113         for(j = 1 ; j <= s2.length() ; ++j)
114         {
115             if(s1[i-1] == s2[j-1])
116             {
117                 dp[i][j] = dp[i-1][j-1];
118             }
119             else
120             {
121                 dp[i][j] = dp[i-1][j] + 1;
122                 dp[i][j] = min(dp[i][j],dp[i][j-1]+1);
123                 dp[i][j] = min(dp[i][j],dp[i-1][j-1]+1);
124             }
125         }
126     }
127     return dp[s1.length()][s2.length()];
128 }
129
130 int main()
131 {
132     memset(opt,-1,sizeof(opt));
133     string s1("abc");
134     string s2("ab");
135     cout<<calSim_3(s1,s2);
136     return 0;
137 }

我的代码里没有加边界情况检查,这一点很重要,不要向我学习,O(∩_∩)O~~

编程之美--3.3

时间: 2024-08-08 00:26:46

编程之美--3.3的相关文章

编程之美-分层遍历二叉树

问题:给定一个二叉树,要求按分层遍历该二叉树,即从上到下按层次访问该二叉树(每一层将单独输出一行),每一层要求访问的顺序为从左到右,并将节点依次编号.那么分层遍历如图的二叉树,正确的输出应该为: <span style="font-size:14px;">1 2 3 4 5 6 7 8</span> 书中还给出了问题2:打印二叉树中的某层次的节点(从左到右),其中根结点为第0层,成功返回true,失败返回false 分析与解法 关于二叉树的问题,由于其本身固有的

读书问题之《编程之美》 -----12061161 赵梓皓

我阅读的书是<编程之美> 刚开始的时候阅读序,就觉得控制cpu利用率这个问题很好玩,所以重点看了这部分和解决办法,问题也都大部分是这部分的.那么问题就来了(挖掘机技术xxx?中国山东找蓝翔) 咳咳,问题在下面: 1.关于问题的提出.(也是一点点建议) 本书的主要内容是告诉读者如何思考问题和解决问题.但是提出问题也是很重要的,正如爱因斯坦所说“提出一个问题往往比解决一个问题更重要”,很多面试题(比如井盖为啥是圆的)我觉得正常人很少会想到.所以,这个问题是怎么想出来的...我很好奇.也希望作者能够

《编程之美》3.6判断链表是否相交之扩展:链表找环方法证明

先看看原题:<编程之美>3.6编程判断两个链表是否相交,原题假设两个链表不带环. 为了防止剧透使得没看过原题目的读者丧失思考的乐趣,我把最好的解法隐藏起来.由于这个问题本身的解答并不是本文的重点,扩展问题也采用这种形式呈现. 注:位于(*)符号之间的文字出自于:http://blog.csdn.net/v_july_v/article/details/6447013,作者v_JULY_v. 用指针p1.p2分别指向两个链表头,不断后移:最后到达各自表尾时,若p1==p2,那么两个链表必相交 用

编程之美之买票找零

题目:假设有2N个人在排队买票,其中有N个人手持50元的钞票,另外有N个人手持100元的钞票,假设开始售票时,售票处没有零钱,问这2N个人有多少种排队方式,不至使售票处出现找不开钱的局面? 分析:队伍的序号标为0,1,...,2n-1,并把50元看作左括号,100元看作右括号,合法序列即括号能完成配对的序列.对于一个合法的序列,第0个一定是左括号,它必然与某个右括号配对,记其位置为k.那么从1到k-1.k+1到2n-1也分别是两个合法序列.那么,k必然是奇数(1到k-1一共有偶数个),设k=2i

【编程之美】java实现重建二叉树

package com.cn.binarytree.utils; /** * @author 刘利娟 [email protected] * @version 创建时间:2014年7月20日 下午2:03:30 类说明: */ class Node { Node left; Node right; char chValue; Node(char chValue) { left = null; right = null; this.chValue = chValue; } } public cla

编程之美之字符串移位包含问题

[题目] 给定两个字符串s1和s2,要求判断s2是否能够被通过s1做循环移位(rotate)得到的字符串包含.例如,S1=AABCD和s2=CDAA,返回true:给定s1=ABCD和s2=ACBD,返回false. [分析] [思路一] 从题目中可以看出,我们可以使用最直接的方法对S1进行循环移动,再进行字符串包含的判断,从而遍历其所有的可能性. 字符串循环移动,时间复杂度为O(n),字符串包含判断,采用普通的方法,时间复杂度为O(n*m),总体复杂度为O(n*n*m). 字符串包含判断,若采

读《编程之美》读后感

读完<编程之美>后,我觉得这并不是简简单单的一本有关于编程的书,本书强调的不仅仅是程序或者考题本身,而是思维.这就和小学时看到数学奥林匹克竞赛的题一样,重要的不是套路或者定式,而在于独立思考时被自己激活的无数脑细胞.对于程序,也是一样,思维,才是程序的精髓所在.正如作者所言,书中展现的题目和分析,犹如海滩上美丽的石子和漂亮的贝壳那样,反映出造化之美,编程之美.该书的目的不仅在于揭开微软面试的神秘面纱,更是鼓励更多的编程爱好者从中收获自己的想法,开阔自己的眼界.作者更希望让面试者和被面试者都能够

求二进制数中1的个数(编程之美)

求二进制数中1的个数 继京东618店庆时买的<编程之美>这本书,翻了翻,发现里面的题还是挺有意思的,看起来我们觉得很简单的题目,解法却有很多很多种,真是一个比一个巧妙,于是,决定记录一下. 书中的题目如下 对于一个字节(8bit)的无符号数,求其二进制表示中"1"的个数,要求算法的执行效率尽可能高. 就像书中给我们说的一样,我们一般人可能想到的解决方法如下 int countOne(int n){ int count=0; while(n){ if(n%2==1){ cou

求子数组之和的最大值——编程之美 2.14 扩展问题 正确实现

使用动态规划求最大子数字和: s[i]表示data[i~n-1]以元素i开始的最大子数组和,a[i]表示data[i~n-1]中的最大子数组和 : s[i]=max(s[i+1]+data[i], data[i]); a[i]=max(a[i+1], s[i]); 由于数组s,a递推的时候,都只用到数组的前一个变量,所以可以用滚动数组节省空间. 扩展问题: 1) 如果数组首尾相连,即允许找到一组数字(A[i],···,A[n-1], A[0],···, A[j]),请使其和最大,怎么办?(书中答

编程之美-2.11 扩展 寻找距离最远的两个点

一.问题描述 平面上有n个点,如何寻找距离最远的两个点? 二.解题思路 第一步,寻找凸包(因为最远距离的两个点一定在凸包上) 第二步,用旋转卡(qia)壳 寻找距离最大的点 凸包和旋转卡壳算法参见http://blog.csdn.net/kaytowin/article/details/5140111 三.代码实现 #include<iostream> #include<vector> #include<algorithm> #include<cmath>