1. 程式人生 > >計算字串的相似度/華為機試(C/C++)

計算字串的相似度/華為機試(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的最右下角就是最終結果,即最小編輯代價。