計算字串的相似度/華為機試(C/C++)
題目描述
對於不同的字串,我們希望能有辦法判斷相似程度,我們定義了一套操作方法來把兩個不相同的字串變得相同,具體的操作方法如下:
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
程式碼:
//第七十七題 計算字串的相似度 #include<iostream> #include<string> #include<vector> #include<algorithm> using namespace std; int main() { string a, b; while (cin >> a >> b) { string res = "1/"; int n = (int)a.size(), m = (int)b.size(); vector<vector<int>>dp(n + 1, vector<int>(m + 1, 0)); dp[0][0] = 0;//dp[x][y]代表將a字串前x個字元修改成b字串前y個字元 for (int i = 1; i <= m; ++i) dp[0][i] = i; for (int i = 1; i <= n; ++i) dp[i][0] = i; for (int i = 1; i <= n; ++i) { for (int j = 1; j <= m; ++j) { int one = dp[i - 1][j] + 1, two = dp[i][j - 1] + 1, three = dp[i - 1][j - 1]; if (a[i - 1] != b[j - 1]) three += 1; dp[i][j] = min(min(one, two), three); } } res += to_string(1 + dp[n][m]); cout << res << endl; } return 0; }
這道題其實簡單的理解就是為了求字串的最小編輯代價,也是一個經典的動態規劃題,複雜度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]的值來至於下面的幾種情況:
(
1
)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
;
(
2
)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
;
(
3
) 如果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
;
(
4
) 如果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的最右下角就是最終結果,即最小編輯代價。