1.编辑距离
/*
* 最小编辑代价
* */
public int minCost(String str1,String str2,int ic,int dc,int rc){
if(str1==null||str2==null) return 0;
char s1[]=str1.toCharArray();
char s2[]=str2.toCharArray();
int n1=s1.length;
int n2=s2.length;
int dp[][]=new int[n1+1][n2+1];//dp[i][j]表示s1中前i-1个字符s1[0...i-1]转化为s2中前j-1个字符s2[0...j-1]需要的最小编辑代价.
// dp[0][0]代表''->'',所以dp[0][0]=0
for(int i=1;i<=n1;i++){//用s1[0...i]转化为''的最小编辑代价
dp[i][0]=i*dc;
}
for(int j=1;j<=n2;j++){//用‘’转化为s2[0...j]的最小编辑代价
dp[0][j]=j*ic;
}
for(int i=1;i<=n1;i++){
for(int j=1;j<=n2;j++){
if(s1[i-1]==s2[j-1]){//s1[i-1]==s[j-1]时,s1[0...i-1]转化为s2[0...j-1]的代价就是 s1[0...i-2]转化为s2[0...j-2],即dp[i-1][j-1]
dp[i][j]=dp[i-1][j-1];
}else{//s1[i]!=s[j]时,s1[0...i-1]转化为s2[0...j-1]的代价就是 s1[0...i-2]转化为s2[0...j-2]的代价加上一个替换操作(s1[i-1]->s2[i-1])的代价,即dp[i-1][j-1]+rc.
dp[i][j]=dp[i-1][j-1]+rc;
}
dp[i][j]=Math.min(dp[i][j],dp[i-1][j]+rc);//比较此时的代价取小:用s1[0...i-2]编辑成s2[0...j-1]的代价,加上一个删除s1[i-1]的操作
dp[i][j]=Math.min(dp[i][j],dp[i][j-1]+ic);//比较此时的代价取小:用s1[0...i-1]编辑成s2[0...j-2]的代价,加上一个添入s2[i-1]的操作
}
}
return dp[n1][n2];
}
/*
* 题目:编辑距离
* 题目描述:
* 给定两个单词 word1 和 word2,计算出将 word1 转换成 word2 所使用的最少操作数 。
* 你可以对一个单词进行如下三种操作:
* 插入一个字符;删除一个字符;替换一个字符
* */
public int minDistance2(String word1, String word2) {
return minCost(word1,word2,1,1,1);
}
2.复制粘贴字符
/*
* 题目描述:复制粘贴字符
* 题目描述:最开始只有一个字符 A,问最少需要多少次操作能够得到 n 个字符 A,每次操作可以复制当前所有的字符,或者粘贴。
*
* */
public int minSteps(int n) {
int dp[]=new int[n+1];//dp[i]表示得到i个字符需要的最少步数
dp[1]=0;
/*
* 得到i个字符的方式只能是如下两种方案之一:(比较所有方案找到操作次数最少的那个)
* 1.复制1个字符后,粘贴i-1次
* 2.找到i的因数j,复制1次(i/j)个字符,粘贴j-1次。(第二种方式计算dp[i]的前提是已知dp[i/j],所以可以用动态规划的方式,依次计算dp[i]并保存)
* */
for(int i=2;i<=n;i++){
dp[i]=i;
for(int j=2;j<=Math.sqrt(n);j++){
if(i%j==0) dp[i]=Math.min(dp[i],dp[i/j]+j);
}
}
return dp[n];
}