/*----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 ", dp[t^1][m]); } return 0; }