題目描述
對於不同的字符串,我們希望能有辦法判斷相似程度,我們定義了一套操作方法來把兩個不相同的字符串變得相同,具體的操作方法如下:
1 修改一個字符,如把“a”替換爲“b”。
2 增加一個字符,如把“abdd”變爲“aebdd”。
3 刪除一個字符,如把“travelling”變爲“traveling”。
比如,對於“abcdefg”和“abcdef”兩個字符串來說,我們認爲可以通過增加和減少一個“g”的方式來達到目的。上面的兩種方案,都只需要一次操作。把這個操作所需要的次數定義爲兩個字符串的距離,而相似度等於“距離+1”的倒數。也就是說,“abcdefg”和“abcdef”的距離爲1,相似度爲1/2=0.5.
給定任意兩個字符串,你是否能寫出一個算法來計算出它們的相似度呢?
請實現如下接口
/* 功能:計算字符串的相似度
* 輸入:pucAExpression/ pucBExpression:字符串格式,如: “abcdef”
* 返回:字符串的相似度,相似度等於“距離+1”的倒數,結果請用1/字符串的形式,如1/2
*/
public static String calculateStringDistance(String expressionA, String expressionB)
{
/* 請實現*/
return null;
}約束:
1、PucAExpression/ PucBExpression字符串中的有效字符包括26個小寫字母。
2、PucAExpression/ PucBExpression算術表達式的有效性由調用者保證;
3、超過result範圍導致信息無法正確表達的,返回null。輸入描述:
輸入兩個字符串- 輸出描述:
輸出相似度,string類型 - 示例1
輸入
abcdef
abcdefg
輸出
1/2
實現代碼
思路:
這道題其實簡單的理解就是爲了求字符串的最小編輯代價,也是一個經典的動態規劃題,複雜度O(M*N)
1.求解狀態轉移矩陣dp[M + 1][N + 1],dp[i][j] 的值代表的是str1[0…i-1]編輯爲str2[0…j-1]的最小代價。
2.計算過程:
1)dp[0][0] = 0,表示str1空的字串編輯爲str2空的字串代價爲0。
2)矩陣dp第一列即爲dp[0…M-1][0],dp[i][0] 表示str1[0…i-1]編輯爲空串的最小代價,所以就是將str1[0..M-1]的字符刪掉的代價所以dp[i][0] = i;
3) 同2),那str2[0…j-1]編輯的代價,dp[0][j] = j;
4) 接下來的位置就按照從左到右,從上到下來計算,dp[i][j]的值來至於下面的幾種情況:
①str1[0…i-1]可以先編輯爲str1[0..i-2],也就是刪除字符str1[i-1],然後由str1[0..i-2]編輯爲str2[0…j-1],dp[i-1][j]表示str1[0..i-2]編輯爲str2[0…j-1]的最小代價,
那麼dp[i][j]可能等於dp[i -1][j] + 1;
②str1[0…i-1]可以先編輯爲str1[0..i-2],然後將str2[0..j-2]插入字符str2[j-1],編輯成str2[0…j-1],dp[i][j-1]表示str1[0..i-1]編輯成str2[0…j-2]的最小代價,
那麼dp[i][j] 可能等於dp[i][j-1] + 1;
③ 如果str1[i - 1]!=str2[j-1] ,那麼先把str1[0..i-1]中的str1[0..i-2]的部分邊長str2[0..j-2],然後把字符str1[i-1]替換爲str2[j-1],這樣str1[0..i-1]就編輯成爲str2[0…j-1]了,dp[i - 1][j - 1]表示
str1[0..i-2]編輯爲str2[0..j-2]的最小代價,那麼dp[i ][j]可能等於dp[i - 1][j - 1] + 1;
④如果str1[i - 1]==str2[j-1] ,那麼先把str1[0..i-1]中的str1[0..i-2]的部分邊長str2[0..j-2],因爲此時 str1[i - 1]==str2[j-1] ,所以str1[0..i-1]已經編輯爲str2[0..j-1]了,dp[i - 1][j - 1]表示str1[0..i-2]編輯爲str2[0..j-2]的最小代價, 那麼dp[i ][j]可能等於dp[i - 1][j - 1]。
上述的4中情況取最小值,dp的最右下角就是最終結果,即最小編輯代價。
package cn.c_shuang.demo76;
import java.util.Scanner;
/**
* 計算字符串的相似度
* @author Cshuang
*
*/
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while(in.hasNext()){
String strA=in.nextLine();
String strB=in.nextLine();
int result = caculate(strA,strB)+1;
System.out.println("1/"+result);
}
in.close();
}
private static int caculate(String a, String b) {
int n = a.length();
int m = b.length();
char[] aCh = a.toCharArray();
char[] bCh = b.toCharArray();
int[][] dp = new int[n+1][m+1];
if(n==0)
return m;
if(m==0)
return n;
for(int i=0;i<n+1;i++){//初始化
dp[i][0]=i;
}
for(int i=0;i<m+1;i++){//初始化
dp[0][i]=i;
}
for(int i=1;i<n+1;i++){
for(int j=1;j<m+1;j++){
if(aCh[i-1]==bCh[j-1])
dp[i][j]=dp[i-1][j-1];
else{
dp[i][j]=Math.min(dp[i-1][j]+1, Math.min(dp[i][j-1]+1, dp[i-1][j-1]+1));
}
}
}
return dp[n][m];
}
}