2021.1.4 省选训练 CF1363F

看到n=2000后知道时间复杂度大概在n^2级别

f[i][j]:表示S的前i个字符和T的前j个字符匹配的最小花费。

1、f[i][j]=f[i-1][j]+1 把之前借的还了(预支后面的)

2、f[i][j]=f[i][j-1] 借后面的补这个(条件:S后面有多余的当前T的这个字符)

3、f[i][j]=f[i-1][j-1] 易得(条件:s[i]==t[j])

 

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #define N 2005
 6 #define inf 2e9
 7 using namespace std;
 8 int n,f[N][N];
 9 int s[N][27],t[N][27];
10 char a[N],b[N];
11 int main()
12 {
13     int T;
14     scanf("%d",&T);
15     while(T--)
16     {
17         memset(s,0,sizeof(s));
18         memset(t,0,sizeof(t));
19         scanf("%d%s%s",&n,a+1,b+1);
20         for(int i=1;i<=n;i++) s[i][a[i]-'a'+1]++,t[i][b[i]-'a'+1]++;
21         for(int i=1;i<=n;i++)
22             for(int j=1;j<=26;j++)
23                 s[i][j]+=s[i-1][j],t[i][j]+=t[i-1][j];
24         bool Flag=1;
25         for(int i=1;i<=26;i++)
26             if(s[n][i]!=t[n][i]){printf("-1\n");Flag=0;break;}//判断组成字符串的字符是否相同 
27         if(!Flag) continue;
28         for(int i=0;i<=n+1;i++)//手动重置,节约时间 
29             for(int j=0;j<=n+1;j++)
30                 f[i][j]=inf;
31         for(int i=0;i<=n;i++) f[0][i]=0;//预处理(细节) 
32         for(int i=1;i<=n;i++)
33             for(int j=i;j<=n;j++)
34             {
35                 if(a[i]==b[j]) f[i][j]=f[i-1][j-1];
36                 if(s[i][b[j]-'a'+1]<t[j][b[j]-'a'+1]) f[i][j]=min(f[i][j],f[i][j-1]);//更新条件!!!(错) 
37                 f[i][j]=min(f[i][j],f[i-1][j]+1);
38                 //printf("f[%d][%d]=%d\n",i,j,f[i][j]);
39             }
40         printf("%d\n",f[n][n]);
41     }
42     return 0;
43 }
View Code

 

posted @ 2021-01-04 21:21  骑着蜗牛去战斗  阅读(9)  评论(0编辑  收藏  举报