题意:
现在有一个s串,每次可以找一个子串向右循环移位1格,问你变成t串最少需要几步
题解:
从左往右做的话,很明显每次最多只需要移一次即可,那么我们需要找到最多的位置使得它不用移动,那么这看起来是个lcs,但是有两个限制:
首先s只能往左移,那么也就是说在做lcs的时候,只能找比s当前枚举到的位置大的地方进行匹配。
还有就是t串的当前位置已有的26个字母数量每个都需要>=s串,否则的话,还需要从后面去找,此时不能进行转移。
#include<bits/stdc++.h>
using namespace std;
const int N=2e3+5;
char s[N],t[N];
int dp[N][N],num[2][26][N];
int main()
{
int tim;
scanf("%d",&tim);
while(tim--){
int n;
scanf("%d%s%s",&n,s+1,t+1);
memset(num,0,sizeof(num));
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
dp[i][j]=0;
for(int i=1;i<=n;i++){
for(int j=0;j<26;j++)
for(int k=0;k<=1;k++)
num[k][j][i]=num[k][j][i-1];
num[0][s[i]-'a'][i]++;
num[1][t[i]-'a'][i]++;
}
int ans=0;
for(int i=0;i<26;i++){
if(num[0][i][n]!=num[1][i][n]){
ans=-1;
break;
}
}
if(ans==-1){
printf("-1\n");
continue;
}
for(int i=1;i<=n;i++){
for(int j=i;j<=n;j++){
dp[i][j]=dp[i-1][j-1];
int f=0;
for(int k=0;k<26;k++)
if(num[0][k][i]>num[1][k][j])
f=1;
if(s[i]==t[j]&&!f)
dp[i][j]=dp[i-1][j-1]+1;
dp[i][j]=max(dp[i-1][j],max(dp[i][j],dp[i][j-1]));
}
}
printf("%d\n",n-dp[n][n]);
}
return 0;
}