题面
题意
思路
这是一道紫书上面的动态规划题,一直想不到思路,过了两天看书后面的题解,豁然开朗,用
d
[
i
]
[
j
]
d[i][j]
d[i][j]表示取前i个s的元素和前j个t的元素时的最小代价,显然只能由
d
[
i
]
[
j
−
1
]
和
d
[
i
−
1
]
[
j
]
d[i][j-1]和d[i-1][j]
d[i][j−1]和d[i−1][j]转移得到,由
d
[
i
]
[
j
−
1
]
d[i][j-1]
d[i][j−1]转移,代价为
c
n
t
[
i
]
[
j
−
1
]
cnt[i][j-1]
cnt[i][j−1](取s的前i个元素和t的前j个元素时,已经出现且未结束的元素个数),由
d
[
i
−
1
]
[
j
]
d[i-1][j]
d[i−1][j]转移也同理。
所以得到状态转移方程:
d
[
i
]
[
j
]
=
m
i
n
(
d
[
i
]
[
j
−
1
]
+
c
n
t
[
i
]
[
j
−
1
]
,
d
[
i
−
1
]
[
j
]
+
c
n
t
[
i
−
1
]
[
j
]
)
d[i][j]=min(d[i][j-1]+cnt[i][j-1],d[i-1][j]+cnt[i-1][j])
d[i][j]=min(d[i][j−1]+cnt[i][j−1],d[i−1][j]+cnt[i−1][j])
现在就是要解决如何求
c
n
t
[
i
]
[
j
]
cnt[i][j]
cnt[i][j]
代码如下
预处理(记录元素在s,t里面的开始和终止位置)
for (int i = 1; i <= lens; i++)
{
int cur = s[i] - 'A';
ss[cur] = min(ss[cur], i);
es[cur] = i;
}
for (int i = 1; i <= lent; i++)
{
int cur = t[i] - 'A';
st[cur] = min(st[cur], i);
et[cur] = i;
}
求 c n t [ i ] [ j ] cnt[i][j] cnt[i][j]
if (i)//其实从从c[i-1][j]和c[i][j-1]转移都一样,只是0要特判
{
cnt[i][j] = cnt[i - 1][j];
if (ss[s[i] - 'A'] == i && st[s[i] - 'A'] > j)
cnt[i][j]++;
if (es[s[i] - 'A'] == i && et[s[i] - 'A'] <= j)
cnt[i][j]--;
}
else if (j)
{
cnt[i][j] = cnt[i][j - 1];
if (st[t[j] - 'A'] == j && ss[t[j] - 'A'] > i)
cnt[i][j]++;
if (et[t[j] - 'A'] == j && es[t[j] - 'A'] <= i)
cnt[i][j]--;
}
else if (i == 0 && j == 0)
cnt[i][j] = 0;
一开始以为这个代码在由元素只出现一次时会有bug,其实不会,如果有元素只出现一次,一定会执行cnt++和cnt–,相当于不变,还有 d [ i ] [ j ] d[i][j] d[i][j]并不是真正取s前i个t前j个的最小代价,而是取s前i个t前j个并且默认在最后一个元素所以元素都终止的代价,这个需要思考一波。
代码
#include <bits/stdc++.h>
using namespace std;
const int maxn = 5100;
const int inf = 0x3f3f3f3f;
int d[maxn][maxn], cnt[maxn][maxn];
int ss[30], st[30], es[30], et[30];
int main()
{
int t;
cin >> t;
while (t--)
{
char s[maxn], t[maxn];
scanf("%s%s", s + 1, t + 1);
int lens = strlen(s + 1);
int lent = strlen(t + 1);
memset(ss, inf, sizeof(ss));
memset(st, inf, sizeof(st));
memset(es, 0, sizeof(es));
memset(et, 0, sizeof(et));
for (int i = 1; i <= lens; i++)
{
int cur = s[i] - 'A';
ss[cur] = min(ss[cur], i);
es[cur] = i;
}
for (int i = 1; i <= lent; i++)
{
int cur = t[i] - 'A';
st[cur] = min(st[cur], i);
et[cur] = i;
}
for (int i = 0; i <= lens; i++)
{
for (int j = 0; j <= lent; j++)
{
int u = inf, v = inf;
if (i == 0 && j == 0)
{
d[i][j] = 0;
}
else
{
if (i)
{
u = d[i - 1][j] + cnt[i - 1][j];
}
if (j)
{
v = d[i][j - 1] + cnt[i][j - 1];
}
d[i][j] = min(u, v);
}
if (i)
{
cnt[i][j] = cnt[i - 1][j];
if (ss[s[i] - 'A'] == i && st[s[i] - 'A'] > j)
cnt[i][j]++;
if (es[s[i] - 'A'] == i && et[s[i] - 'A'] <= j)
cnt[i][j]--;
}
else if (j)
{
cnt[i][j] = cnt[i][j - 1];
if (st[t[j] - 'A'] == j && ss[t[j] - 'A'] > i)
cnt[i][j]++;
if (et[t[j] - 'A'] == j && es[t[j] - 'A'] <= i)
cnt[i][j]--;
}
else if (i == 0 && j == 0)
cnt[i][j] = 0;
}
}
cout << d[lens][lent] << endl;
}
return 0;
}