#实验题目
设有字符串X,我们称在X的头尾及中间插入任意多个空格后构成的新字符串为X的扩展串,如字符串X为“abcbcd”,则字符串“abcb□cd”,“□a□bcbcd□”和“abcb□cd□”都是X的扩展串,这里“□”代表空格字符。如果A1是字符串A的扩展串,B1是字符串B的扩展串,A1与B1具有相同的长度,那么我扪定义字符串A1与B1的距离为相应位置上的字符的距离总和,而两个非空格字符的距离定义为它们的ASCII码的差的绝对值,空格字符与其他任意字符之间的距离为已知的定值K,空格字符与空格字符的距离为0。在字符串A、B的所有扩展串中,必定存在两个等长的扩展串A1、B1,使得A1与B1之间的距离达到最小,我们将这一距离定义为字符串A、B的距离。请你写一个程序,求出字符串A、B的距离。
输入:第一行为字符串A,第二行为字符串B。A、B均由小写字母组成且长度均不超过2000。第三行为一个整数K(1≤K≤100),表示空格与其他字符的距离。
输出:字符串A、B的距离。
#问题分析
使用动态规划
设字符串为 A{ a1… an }, B{ b1… bm }
距离最小的扩展字符串为 C{ c1 … cx }, D{ d1… dx }
1.若cx = an , dx = bm , Cx-1和 Dx-1是 An-1 和 Bm-1 的距离最小的扩展
2.若cx != an , dx = bm,Cx-1和 Dx-1是 An 和 Bm-1 的距离最小的扩展
3.若cx = an , dx != bm,Cx-1和 Dx-1是 An-1 和 Bm 的距离最小的扩展
#递归关系
dis[i][j]表示A(1…i)和B(1…j)的扩展距离,则
dis[i][j] = min ( dis[i][j -1]+s(B[j],’ ‘) , dis[i-1][j]+s(A[i],’ ') , dis[i-1][j-1]+s(A[i]-B[j]) )
#初始值
dis[0][0] = 0;
dis[i][0] = k*(i-Xi); // Xi表示原来A中已经包含的空格数
dis[0][j] = k*(j-Xj); // Xj表示原来B中已经包含的空格数
#代码
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
int dis[2001][2001];
int Distance(string A, string B, int k) {
int lenA = A.length();
int lenB = B.length();
int Xi = 0, Xj = 0;
for (int i = 0; i < lenA; i++) {
if (A[i] == ' ') Xi++; //计算A本身的空格数
}
for (int i = 0; i < lenB; i++) {
if (B[i] == ' ') Xj++; //计算B本身的空格数
}
//初始值
dis[0][0] = 0;
for (int i = 1; i <= lenA; i++)
dis[i][0] = k*(i-Xi);
for (int j = 1; j <= lenB; j++)
dis[0][j] = k*(j-Xj);
for (int i = 1; i <= lenA; i++) {
for (int j = 1; j <= lenB; j++) {
int min = dis[i][j - 1] + k;
if (dis[i - 1][j] + k < min) min = dis[i - 1][j] + k;
else if (dis[i - 1][j - 1] + abs(A[i-1] - B[j-1]) < min) min = dis[i - 1][j - 1] +abs(A[i-1] - B[j-1]);
dis[i][j] = min;
}
}
return dis[lenA][lenB];
}
int main() {
string A;
string B;
int k;
getline(cin,A);
getline(cin, B); //以回车为标准,防止字符串中出现空格情况
cin >> k;
int dis = Distance(A, B, k);
cout << "The distance between A and B is:" << dis << endl;
}