标签:
/*----UVa1625 Color Length
--用dp[i][j]表示当前两个串分别移走到第i和第个元素j时所获得的目标函数最优值,首先计算出两个序列中的每个元素开始和
结束的位置,在计算dp[i][j]的同时,还需要记住当前有多少颜色已经开始但是没有结束,这样不必关心每一个元素的L(c),
在程序递进计算的同时,只需要每次累加已经开始还没结束的元素个数即可。
*/
#define _CRT_SECURE_NO_DEPRECATE
#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
#define INF 0x3f3f3f3f
const int maxn = 5000 + 10;
const int size = 26;
char p[maxn], q[maxn]; //保存p,q串
int sp[size], sq[size], ep[size], eq[size]; //记录p和q结束和开始的位置
int dp[2][maxn], c[2][maxn]; //c[i][j]记录当前有多少序列一开始但是未结束
int main(){
int i, T,n,m,j,id;
scanf("%d", &T);
while (T--){
scanf("%s%s", p + 1, q + 1);
n = strlen(p + 1);
m = strlen(q + 1);
for (i = 1; i <= n; i++) p[i] -= ‘A‘;
for (j = 1; j <= m; j++)q[j] -= ‘A‘;
//计算p和q中开始序列和结束序列
memset(sp, 0x3f, sizeof(sp));
memset(sq, 0x3f, sizeof(sq));
memset(ep, 0, sizeof(ep));
memset(eq, 0, sizeof(eq));
for (i = 1; i <= n; i++){
sp[p[i]] = min(sp[p[i]], i);
ep[p[i]] = i;
}
for (i = 1; i <= m; i++){
sq[q[i]] = min(sq[q[i]], i);
eq[q[i]] = i;
}
int t = 0;
for (i = 0; i <= n; i++){
for (j = 0; j <= m; j++){
if (!i&&!j){ dp[i][j] = c[i][j] = 0; continue; }
int v = INF, u = INF;
if (i) v = dp[t ^ 1][j] + c[t ^ 1][j];
if (j) u = dp[t][j - 1] + c[t][j - 1];
//dp[i][j]=min(dp[i][j-1]+c[i][j-1],dp[i-1][j]+c[i-1][j]);
if (v < u){
dp[t][j] = v; c[t][j] = c[t ^ 1][j];
id = p[i];
//如果p[i]还没有出现过,并且在q[j]后面还有
if (sp[id] == i&&sq[id]>j)c[t][j]++;
//如果p[i]之前出现过,并且此次为最后一次出现
if (ep[id] == i&&eq[id] <= j)c[t][j]--;
}
else{
dp[t][j] = u; c[t][j] = c[t][j - 1];
id = q[j];
if (sq[id] == j&&sp[id] > i)c[t][j]++;
if (eq[id] == j&&ep[id] <= i)c[t][j]--;
}
}
t ^= 1;
}
printf("%d\n", dp[t^1][m]);
}
return 0;
}
标签:
原文地址:http://www.cnblogs.com/td15980891505/p/5791293.html