Codeforces Round #646 (Div. 2)F. Rotating Substrings(dp)

题目:click
题意:在这里插入图片描述利用该操作,问最小的操作次数使得s变为t,如果不可能则-1.

思路来源:https://www.bilibili.com/video/BV13T4y1J73t?p=6
记录一下这个dp,切入点在最长的公共子序列,答案min,肯定需要公共子序列max,n-max(公共子序列的长度)即答案,我们只需要改变不是最长公共子序列的字符,但是注意就只能向前移动,
所以每次匹配的时候,在者之后的a-z个数s序列一定要大于等于t的,不然无法完成,因为s序列在此之前的非最长公共子序列的字符只能往前面移动,后面的不能匹配到。

#include<cmath>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<istream>
#include<vector>
#include<stack>
#include<set>
#include<map>
#include<algorithm>
#include<queue>
#define inf 0x3f3f3f3f
#define llinf 0x3f3f3f3f3f3f3f3f
#define MAX_len 200005*4
using namespace std;
typedef long long ll;
char s[2010],t[2010];
int dp[2010][2010];
int num1[2010][30];
int num2[2010][30];
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n,i,j;
        scanf("%d",&n);
        scanf("%s",s+1);
        scanf("%s",t+1);
        if(strcmp(s+1,t+1)==0)
        {
            printf("0\n");
            continue;
        }
        memset(num1[n+1],0,sizeof(num1[n+1]));
        memset(num2[n+1],0,sizeof(num2[n+1]));
        for(i=n;i>=1;i--)
        {
            for(j=0;j<26;j++)
            {
                num1[i][j]=num1[i+1][j];
                num2[i][j]=num2[i+1][j];
            }
            num1[i][s[i]-'a']++;
            num2[i][t[i]-'a']++;
        }
        bool flag=true;
        for(i=0;i<26;i++)
        {
            if(num1[1][i]!=num2[1][i])
            {
                flag=false;
                break;
            }
        }
        if(!flag)
        {
            printf("-1\n");
            continue;
        }
        dp[0][0]=0;
        for(i=0;i<=n;i++)
        {
            for(j=0;j<=n;j++)
            {
                if(i)
                    dp[i][j]=dp[i-1][j];
                if(j)
                    dp[i][j]=max(dp[i][j],dp[i][j-1]);
                if(i&&j&&s[i]==t[j])
                {
                    flag=true;
                    for(int k=0;k<26;k++)
                    {
                        if(num1[i+1][k]>=num2[j+1][k])
                            continue;
                        else
                        {
                            flag=false;
                            break;
                        }
                    }
                    if(flag)
                    {
                        dp[i][j]=max(dp[i][j],dp[i-1][j-1]+1);
                    }
                }
            }
        }
        printf("%d\n",n-dp[n][n]);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43958964/article/details/106498757