字符串的扩展距离问题

题目描述:对于长度相同的2个字符串A和B,其距离定义为所有相应位置字符距离之和。2个非空格字符的距离是它们的ASCII码之差的绝对值;空格与空格的距离为0,空格与其他字符的距离为一个定值k。在一般情况下,字符串A和B的长度不一定相同。字符串A的扩展是在A中插入若干空格字符所产生的字符串。在字符串A和B的所有长度相同的扩展中,有一对距离最短的扩展,该距离称为字符串A和B的扩展距离。对于给定的字符串A和B测试数据:

输入:cmc
snmn
2 (分别表示字符串A、B和定值k)

输出:10,设计一个算法,计算其扩展距离。

样例解释:
∗ * 代表空格的话
a: c ∗ ∗ m c ∗ c**m c* cmc
b: ∗ s n m ∗ n *snm*n snmn 这样的话 扩展距离 = 2+2+2+0+2 = 10

算法分析:
这个题我们可以类比于之前的最长公共子序列问题,题目也比较简单,通过动态规划求解,我们定义一个二维数组dp[i][j] 表示第一个字符串已经匹配到第i位,第二个字符串已经匹配到第j位时两者扩展距离的最小值,我们可以看到此时,dp[i][j] 可能由三种情况得到,一种是i和j匹配时扩展距离加上两者的字符的距离dist,另一种是j和(0i-1)中的某一位匹配,剩下i和空格匹配(或者是i和0j-1中某一位匹配,j和空格匹配)此时扩展距离只要加上k就可以了
那么我们很容易得到其中的状态转移方程
d p [ i ] [ j ] = m i n ( d p [ i − 1 ] [ j − 1 ] + d i s t ( i , j ) , m i n ( d p [ i − 1 ] [ j ] + t , d p [ i ] [ j − 1 ] + t ) ) dp[i][j]=min(dp[i-1][j-1]+dist(i,j),min(dp[i-1][j]+t,dp[i][j-1]+t)) dp[i][j]=min(dp[i1][j1]+dist(i,j),min(dp[i1][j]+t,dp[i][j1]+t))
最后考虑一下边界条件,如果i或者j=0的话, dp[i][0]=ik , dp[0][j]=jk;因为都和空格进行了匹配

代码如下

#include <bits/stdc++.h>
using namespace std;
const int maxn=5000;
int dp[maxn][maxn];
string s,k;
int dist(int i,int j)
{
    int p1=s[i-1]-'a';
    int p2=k[j-1]-'a';
    return abs(p1-p2);
}
int main()
{
    memset(dp,0,sizeof(dp));
    cin>>s>>k;
    int t;
    cin>>t;
    int len = max(s.size(),k.size());
    memset(dp,0,sizeof(dp));
    for(int i=1;i<=s.size();i++)
    {
        dp[i][0]=t*i;
    }
    for(int i=1;i<=k.size();i++)
    {
        dp[0][i]=t*i;
    }
    for(int i=1;i<=s.size();i++)
    {
        for(int j=1;j<=k.size();j++)
        {
            dp[i][j]=min(dp[i-1][j-1]+dist(i,j),min(dp[i-1][j]+t,dp[i][j-1]+t));
        }
    }
    int len1=s.size();
    int len2=k.size();
    cout<<dp[len1][len2]<<endl;
    return 0;

}

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值