链接
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;
}