给你两个序列,都由大写字母组成;
每次,把两个序列中的一个的开头字母加在字符串的尾端,然后在那个序列中删掉那个开头字母;
最后得到一个字符串;
这个字符串显然后很多种;
让你找所有字母的L(C)的和的最小值;
L(c)是某个字母在最后的那个字符串中出现的结尾位置和开始位置的差值;
设f[i][j]表示第一个序列1..i全都移除掉了,第二个序列1..j全都移除掉了的最小L(c)和;
这里不能直接算出某个字母的L(C)值,但是能一步一步地累加,比如,你新加了一个字母x,然后在此之前,已有的字符串里面,有字母a,且还有未加入的字母a;
则L(a)的值可以肯定会递增1了;
则可以写出转移方程
这里的cnt[i][j]表示第一个序列前i个字母移出去了,第二个序列前j个字母移出去了所形成的字符串,有多少个字母已经出现了,但是还没有全部出现;
为了获取这个cnt数组;
可以先获取,每个字母在这两个序列中第一次出现和最后一次出现的位置;
然后对于枚举的i和j;
看看每个字母是不是在这个情况下出现了;
这样就能获得cnt数组;
4
用memset会莫名的TLE;
改成循环就过了
#include <bits/stdc++.h>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define LL long long
#define rep1(i,a,b) for (int i = a;i <= b;i++)
#define rep2(i,a,b) for (int i = a;i >= b;i--)
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define ms(x,y) memset(x,y,sizeof x)
#define Open() freopen("F:\rush.txt","r",stdin)
#define Close() ios::sync_with_stdio(0)
typedef pair<int,int> pii;
typedef pair<LL,LL> pll;
const int dx[9] = {0,1,-1,0,0,-1,-1,1,1};
const int dy[9] = {0,0,0,-1,1,-1,1,-1,1};
const double pi = acos(-1.0);
const int N = 5e3;
const int INF = 0x3f3f3f3f;
int dp[N+100][N+100],n,m,cnt[N+100][N+100];
pii a1[27],a2[27];
char s1[N+100],s2[N+100];
int main(){
//Open();
//Close();
int T;
scanf("%d",&T);
while (T--){
scanf("%s",s1+1);
scanf("%s",s2+1);
n = strlen(s1+1),m = strlen(s2+1);
rep1(i,1,26) a1[i].fi = a1[i].se = a2[i].fi = a2[i].se = 0;
//第一次出现
rep1(i,1,n){
int t = s1[i]-'A'+1;
if (a1[t].fi==0) a1[t].fi = i;
}
rep1(i,1,m){
int t = s2[i]-'A'+1;
if (a2[t].fi==0) a2[t].fi = i;
}
//最后一次出现
rep2(i,n,1){
int t = s1[i]-'A'+1;
if (a1[t].se==0) a1[t].se = i;
}
rep2(i,m,1){
int t = s2[i]-'A'+1;
if (a2[t].se==0) a2[t].se = i;
}
rep1(i,0,n)
rep1(j,0,m){
int temp = 26;
rep1(k,1,26){
if (a1[k].fi == 0 && a2[k].fi==0){
temp--;
continue;
}
if (a1[k].fi!=0 && a2[k].se==0){
if (i<a1[k].fi){
temp--;
continue;
}
if (a1[k].se<=i){
temp--;
continue;
}
}
if (a1[k].fi==0 && a2[k].se!=0){
if (j<a2[k].fi){
temp--;
continue;
}
if (a2[k].se<=j){
temp--;
continue;
}
}
if (a1[k].fi!=0 && a2[k].fi!=0){
if (i<a1[k].fi && j<a2[k].fi){
temp--;
continue;
}
if (a1[k].se<=i && a2[k].se<=j){
temp--;
continue;
}
}
}
cnt[i][j] = temp;
}
rep1(i,0,n)
rep1(j,0,m)
dp[i][j] = INF;
dp[0][0] = 0;
rep1(i,0,n)
rep1(j,0,m){
if (i-1 >= 0){
dp[i][j] = min(dp[i][j],dp[i-1][j] + cnt[i-1][j]);
}
if (j-1 >= 0){
dp[i][j] = min(dp[i][j],dp[i][j-1] + cnt[i][j-1]);
}
}
cout << dp[n][m] << endl;
}
return 0;
}