题解 CF1363F 【Rotating Substrings】
CF思维题。
观察操作的本质,就是把一个字符拿出来塞到另一个位置(感性分析
要使操作数最小可以想到使用DP。
我们需要一个
第二种是从后面借一个字符
对于当前
在满足有多余字符情况下,这时
第三种是还先前借的字符。因为先前保证还的起,所以现在直接还回去即可,不需要条件。
这时,
Attention
其实读到这里你还没有发现这篇题解与前两篇题解有什么区别。。。
我发题解因为想一个细节想了很久。
就是在还的操作时,如果当前字符
比如
这里
但仔细琢磨下会发现我们更新了
所以并不会影响答案。
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define pre(i,a,b) for(int i=a;i>=b;i--)
#define N 2005
using namespace std;
int n;char s[N],t[N];
int f[N][N],u[N][28],v[N][28];
void solve(){
scanf("%d",&n);
scanf("%s%s",s+1,t+1);
memset(u,0,sizeof(u));
memset(v,0,sizeof(v));
rep(i,1,n)u[i][s[i]-'a']++,v[i][t[i]-'a']++;
rep(i,1,n)rep(j,0,25)u[i][j]+=u[i-1][j],v[i][j]+=v[i-1][j];
rep(i,0,25)if(u[n][i]!=v[n][i]){puts("-1");return ;}
rep(i,0,n)rep(j,0,n)f[i][j]=0x3f3f3f3f;
rep(i,0,n)f[0][i]=0;
rep(i,1,n){
rep(j,i,n){
f[i][j]=f[i-1][j]+1;
if(s[i]==t[j])f[i][j]=min(f[i-1][j-1],f[i][j]);
if(u[i][t[j]-'a']<v[j][t[j]-'a'])f[i][j]=min(f[i][j],f[i][j-1]);
}
}
printf("%d\n",f[n][n]);
}
int main(){
int T;scanf("%d",&T);
while(T--)solve();
return 0;
}
/*
1
3
aab
aba
*/