算法第三章上机实践报告
1.1 问题描述
设A和B是2个字符串。要用最少的字符操作将字符串A转换为字符串B。这里所说的字符操作包括 (1)删除一个字符; (2)插入一个字符; (3)将一个字符改为另一个字符。 将字符串A变换为字符串B所用的最少字符操作数称为字符串A到 B的编辑距离,记为d(A,B)。 对于给定的字符串A和字符串B,计算其编辑距离 d(A,B)。
输入:
第一行是字符串A,文件的第二行是字符串B。
提示:字符串长度不超过2000个字符。
输出:
输出编辑距离d(A,B)
1.2 算法描述
通过找规律找到删除,插入,修改这三个操作的状态转移方程。
定义dp[i][j]为:把串A的第1到i位变成串B的第1到j位的最小步骤。(从1开始,因为0表示空串)。
然后i从1-A.size()遍历,j从1-B.size()遍历——答案就是dp[A.size()][B.size()];
1.3 问题求解:
1.1.1 根据最优子结构性质,列出递归方程式
修改:
令string a="ab",string b="ac";想让ab变成ac,其实就是让ab、ac都退一步变为a、a,然后把a加上c;
退一步就是变成dp[i-1][j-1],加c就是再+1;
即:dp[i][j]=dp[i-1][j-1]+1;
插入:
一般情况下,如果要插入,那么A.size()<B.size();
令string a="ab",string b="cde";
想让ab变成cde:ab先变成cd,再+e;
ab变成cd即dp[i][j]=dp[i][j-1];
加e即要+1;
即:dp[i][j]=dp[i][j-1]+1;
删除:与插入同理。
dp[i][j]=dp[i-1][j]+1;
1.1.2 给出填表法中表的维度、填表范围和填表顺序。
维度:二维。因为要字符串逐一比较。
填表范围:i从1到a.size(),j从1到b.size();
填表顺序:外层循环i,从1加到a.size();内层循环j,从1加到b.size()。
1.1.3 分析该算法的时间和空间复杂度
时间复杂度:O(n2) 二重循环。
空间复杂度:O(n2) 二维数组。
1.3 心得体会(对本次实践收获及疑惑进行总结)
本次实验四道题正好是四种动态规划典型题。
最低通行费:二维数组,规定了只能走的方向(右,下),那么每个点都只能从左、上得到(除了边界),是一个斐波那契数列变形。
最大子段和:前面的数字和不是负数就可以加上。每个dp[i]都要看dp[i-1]。经典的动态规划。
单调递增最长子序列:跟最大字段和类似。
编辑距离问题:可以体现dp定义的妙处。
本次实验的四道题能让我们明显的体会到动态规划的特点、共性,更深刻的了解了动态规划的思想。
2.你对动态规划算法的理解和体会
动态规划,是利用历史记录来避免重复计算的一种算法,是求解决策过程最优化的过程。
因此,很多求“最长最短”“最大最小”都可以用动态规划。
“将原问题拆解成若干子问题,同时保存子问题的答案,使每个子问题只求解一次,最终获得原问题的答案。”