uva1625 Color Length

链接

https://vjudge.net/problem/UVA-1625

题解

f i j f_{ij} fij表示用了第一个串的前 i i i个字母和第二个串的前 j j j个字母组成的串的最小代价
那么最后一次加入的字母要么是 a i a_i ai要么是 b j b_j bj
考虑加入这个字母 x x x的贡献
对于 x x x这个字母,如果是第一次出现,那就没有贡献,否则有 1 1 1的贡献
如果一种字母在当前以出现过的区域和将来要出现的区域都存在,那么这种字母就对答案有 1 1 1的贡献
具体可以用 b i t s e t bitset bitset实现

代码

//dp
#include <bits/stdc++.h>
#define maxn 5010
#define iinf 0x3f3f3f3f
using namespace std;
int f[maxn][maxn], l1, l2;
char a[maxn], b[maxn];
bitset<26> pre1[maxn], pre2[maxn], suf1[maxn], suf2[maxn];
int read(int x=0)
{
    int c, f(1);
    for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-f;
    for(;isdigit(c);c=getchar())x=x*10+c-48;
    return f*x;
}
void init()
{
    int i;
    scanf("%s%s",a+1,b+1);
    l1=strlen(a+1), l2=strlen(b+1);
    for(i=1;i<=l1;i++)
    {
        pre1[i]=pre1[i-1];
        pre1[i].set(a[i]-'A');
    }
    for(i=1;i<=l2;i++)
    {
        pre2[i]=pre2[i-1];
        pre2[i].set(b[i]-'A');
    }
    suf1[l1+1].reset();
    for(i=l1;i;i--)
    {
        suf1[i]=suf1[i+1];
        suf1[i].set(a[i]-'A');
    }
    suf2[l2+1].reset();
    for(i=l2;i;i--)
    {
        suf2[i]=suf2[i+1];
        suf2[i].set(b[i]-'A');
    }
}
void dp()
{
    int i, j;
    for(i=0;i<=l1;i++)for(j=0;j<=l2;j++)
    {
        if(i or j)f[i][j]=iinf;
        else continue;
        if(i)
        {
            auto l=pre1[i-1]|pre2[j], r=suf1[i+1]|suf2[j+1];
            auto t=l&r;
            t.reset(a[i]-'A');
            f[i][j]=min(f[i][j],int( f[i-1][j]+l.test(a[i]-'A')+t.count() ) );
        }
        if(j)
        {
            auto l=pre1[i]|pre2[j-1], r=suf1[i+1]|suf2[j+1];
            auto t=l&r;
            t.reset(b[j]-'A');
            f[i][j]=min(f[i][j],int( f[i][j-1]+l.test(b[j]-'A')+t.count() ) );
        }
    }
    printf("%d\n",f[l1][l2]);
}
int main()
{
    int T(read());
    while(T--)
    {
        init();
        dp();
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值