SPOJ 2325 String Distance (dp+剪枝)

本文介绍了一种计算两个字符串间距离的方法,通过动态规划算法求解,采用滚动数组优化内存使用,并利用题目条件进行剪枝,确保在大数据集上的高效运行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

2325. String Distance

Problem code: STRDIST

Let A = a1a2...ak and B = b1b2...bl be strings of lengths k and l, respectively. The string distance between A and B is defined in the following way (d[i,j] is the distance of substrings a1...ai and b1...bj, where 0 ≤ i ≤ k and 0 ≤ j ≤ l -- i or j being 0 represents the empty substring). The definition for d[i, j] is d[0, 0] = 0 and for (i, j) ≠ (0, 0) d[i, j] is the minimum of all that apply:

  • d[i, j - 1] + 1, if j > 0
  • d[i - 1, j] + 1, if i > 0
  • d[i - 1, j - 1], if i > 0, j > 0, and ai = bj
  • d[i - 1, j - 1] + 1, if i > 0, j > 0, and ai ≠ bj
  • d[i - 2, j - 2] + 1, if i ≥ 2, j ≥ 2, ai = bj-1, and ai-1 = bj

The distance between A and B is equal to d[k,l].

For two given strings A and B, compute their distance knowing that it is not higher than 100.

Input

In the first line, k and l are given, giving the lengths of the strings A and B (1 ≤ k, l ≤ 105). In the second and third lines strings A and B, respectively, are given. A and B contain only lowercase letters of the English alphabet.

Output

In the first line, write one number, the distance between A and B, followed by a newline.

Example

Input:
8 8
computer
kmpjutre

Output:
4


题意:根据那几个要求转移dp值就好了...其实是一种旧的编辑距离问题

题解:首先数组肯定开不到10W*10W的,所以考虑用滚动数组,只需开3*10W就可以了,然后考虑到经常取模,所以开一个数组来保存取模的结果这样快点,不过10W*10W的dp转移还是会超时,但是题目有句很重要的话,说dp的值不会超过100,所以当里外循环的下标超过100的时候就相当于没有意义了,还有字符串相差超过100也没意义了,这里就是关键的剪枝了,剪了这里就可以过了~


#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define INF 999999
int dp[3][100005],mod[100005];
char a[100005],b[100005];
int MIN(int x,int y){ return x<y?x:y; }
int main()
{
    int l,k,i,j,temp;

    //freopen("t","r",stdin);
    for(i=0;i<100005;i++) mod[i]=i%3;
    while(scanf("%d%d",&k,&l)>0)
    {
        scanf("%s%s",a+1,b+1);

        if(strlen(a)-strlen(b)>=100){ printf("100\n"); continue; }
        if(strlen(b)-strlen(a)>=100){ printf("100\n"); continue; }
        for(i=0;i<=l;i++) dp[0][i]=i;
        for(i=1;i<=k;i++)
        {
            if(i>=100) j=i-100;
            else j=0;
            for(;j<=l;j++)
            {
                if(j-i>100) break;
                temp=INF;
                temp=MIN(temp,dp[mod[i-1]][j]+1);
                if(j>0) temp=MIN(temp,dp[mod[i]][j-1]+1);
                if(j>0)
                {
                    if(a[i]==b[j]) temp=MIN(temp,dp[mod[i-1]][j-1]);
                    else temp=MIN(temp,dp[mod[i-1]][j-1]+1);
                    if(i>=2&&j>=2&&a[i]==b[j-1]&&a[i-1]==b[j]) temp=MIN(temp,dp[mod[i-2]][j-2]+1);
                }
                dp[mod[i]][j]=temp;
            }
        }
        printf("%d\n",dp[mod[k]][l]);
    }

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值