字符串距离(动态规划实验)

#实验题目

设有字符串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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值