一.题目描述
NC35最小编辑代价
题目链接:https://www.nowcoder.com/practice/05fed41805ae4394ab6607d0d745c8e4tpId=196&&tqId=37134&rp=1&ru=/activity/oj&qru=/ta/job-code-total/question-ranking
给定两个字符串str1和str2,再给定三个整数ic,dc,rc,分别代表插入、删除、替换一个字符的代价,返回将str1编辑成str2的最小代价。
举例:
str1="abc" str2="adc" ic=5 dc=3 rc=2,从"abc"编辑到"adc"把b替换成d代价最小,为2;
str1="abc" str2="adc" ic=5 dc=3 rc=10,从"abc"编辑到"adc",先删除b再插入d代价最小,为8;
二.算法(暴力搜索)
对于给出的两个字符串a和b,从左向右逐个匹配:
(1)对于a中当前遍历到的字符a[i],如果b[j]相同,则不需要任何操作,继续向右遍历i+1,j+1
(2)如果a[i]!=b[i],可以删除a[i],或者替换a[i],或者插入和b[j]相同的字符,因此存在三种选项所以每次遍历匹配的时候,都存在四种情况
当a[i]==b[j]: i+1和j+1继续比较
当a[i]!=b[j] :
1. 说明a中在i前插入一个元素,i和j+1继续比较
2.说明a中i处元素被替换,i+1和j+1继续比较
3.说明a中i处元素被删除,i+1和j继续比较
/*java代码 开始用暴力搜索去尝试 但是很显然是超时的 读者可以看看 这个暴力搜索 */ import java.util.*; public class Solution { //复杂度比较大,运行超时 public static int minEditCost (String str1, String str2, int ic, int dc, int rc) { return dfs(str1,0,str2,0,ic,dc,rc); } public static int dfs (String str1, int i, String str2, int j,int ic, int dc, int rc) { if(i==str1.length()){ return (str2.length()-j)*ic; } if(j==str2.length()){ return (str1.length()-i)*dc; } if(str1.charAt(i)==str2.charAt(j)){ return dfs(str1,i+1,str2,j+1,ic,dc,rc); } return Math.min(dfs(str1,i,str2,j+1,ic,dc,rc)+ic, Math.min(dfs(str1,i+1,str2,j+1,ic,dc,rc)+rc, dfs(str1,i+1,str2,j,ic,dc,rc)+dc)); } }
时间复杂度:
空间复杂度:
优缺点:时间复杂度很大,但是容易想到
三.算法(动态规划)
(1)动态规划:表示str1的前i个字符编辑成str2的前j个字符需要的最小操作数
(2)边界处理:从表格可以看出来:
1.求第一行dp[0][j],;
2.求第一列dp[i][0],;
(3)状态转移:
1.当i字符等于j字符的时候:相等不需要操作
2.当i字符不等于j字符的时候:的值等于插入、替换和删除的最大值
插入:; 将个字符串转变为前个字符串在插入第j个字符
删除:; 将个字符串转换为前个字符串删除第i个字符
替换:; 个编辑成个字母,再将i替换成j
class Solution { public: int minEditCost(string str1, string str2, int ic, int dc, int rc) { int m = str1.size(); int n = str2.size(); int dp[5005][5005]; //刚开始对边界的初始化 for(int i=0;i<=m;i++) dp[i][0]=i*dc; for(int j=0;j<=n;j++) dp[0][j]=j*ic; for(int i=1; i<=m; i++){ for(int j=1; j<=n; j++){ int a=dp[i][j-1]+ic;//插入 int b=dp[i-1][j]+dc;//删除 int c=dp[i-1][j-1];//替换 if(str1[i-1]!=str2[j-1]) c+=rc; dp[i][j]=min(a, min(b, c)); } } return dp[m][n]; } };
时间复杂度:
空间复杂度:需要额外开辟二维数组
优缺点:效率高,但是状态转移方程比较难想