Description
有两种字符串A,B。长度分别为n,m。现在需要在S里面有序地选出k个子串,且在B中出现的顺序与这k个子串的顺序相同。问这k个子串最大的长度和。
吐槽:题意不清。
有序地的意思是子串从左到右选
选的各个子串不能重复、重叠
100% n,m<=1000 k<=10
Analysis
一眼DP
可是DP有技巧
设
f[i][j][k]
表示
A
到
枚举
i′,j′
其实不需要,再弄一个数组存下来
f
的前缀最大值即可。
Code
#include<cstdio>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int N=1010,K=12;
int n,m,r,f[N][N][K][2];
char a[N],b[N];
int main()
{
freopen("string.in","r",stdin);
freopen("string.out","w",stdout);
int ans=0;
scanf("%d %d %d\n%s\n%s",&n,&m,&r,a+1,b+1);
fo(k,1,r)
{
fo(i,1,n)
{
fo(j,1,m)
{
f[i][j][k][0]=max(f[i][j-1][k][0],f[i-1][j][k][0]);
f[i][j][k][0]=max(f[i][j][k][0],f[i][j][k][1]);
if(a[i]==b[j])
{
f[i][j][k][1]=max(f[i][j][k][1],f[i-1][j-1][k-1][0]+1);
f[i][j][k][1]=max(f[i][j][k][1],f[i-1][j-1][k][1]+1);
f[i][j][k][0]=max(f[i][j][k][0],f[i][j][k][1]);
}
if(k==r) ans=max(ans,f[i][j][r][1]);
}
}
}
printf("%d",ans);
return 0;
}