CF682D

Solution

比较经典的 d p dp dp​。

考虑 f i , j , k f_{i,j,k} fi,j,k 表示 S S S 到了第 i i i 位, T T T 到了第 j j j 位,已经选择了 k k k 个子串的最大长度和。

但是由于当前位能否匹配与上一位有关,因此再开一维 0 / 1 0/1 0/1 表示 i − 1 i-1 i1 j − 1 j-1 j1 是否匹配。

转移:

如果 S i = T j S_i=T_j Si=Tj,说明当前位可以匹配,那么 f i , j , k , 1 = max ⁡ ( f i − 1 , j − 1 , k , 1 , f i − 1 , j − 1 , k − 1 , 0 ) + 1 f_{i,j,k,1}=\max(f_{i-1,j-1,k,1},f_{i-1,j-1,k-1,0})+1 fi,j,k,1=max(fi1,j1,k,1,fi1,j1,k1,0)+1

然后 f i , j , k , 0 = max ⁡ { f i − 1 , j − 1 , k , 0 / 1 , f i , j − 1 , k , 0 / 1 , f i − 1 , j , k , 0 / 1 } f_{i,j,k,0}=\max\{f_{i-1,j-1,k,0/1},f_{i,j-1,k,0/1},f_{i-1,j,k,0/1}\} fi,j,k,0=max{fi1,j1,k,0/1,fi,j1,k,0/1,fi1,j,k,0/1}

因为可以有空串,所以 a n s = max ⁡ { f n , m , 1 -> k , 0 / 1 } ans=\max\{f_{n,m,1\texttt{->}k,0/1}\} ans=max{fn,m,1->k,0/1}

Code

#include<cstdio>
#include<algorithm>
#define N 1005
#define K 11
using namespace std;
int n,m,kk,x,ans,f[N][N][K][3];
char ch,a[N],b[N];
int main()
{
	scanf("%d%d%d",&n,&m,&kk);
	ch=getchar();
	while (ch<'a'||ch>'z') ch=getchar();
	x=0;
	while (ch>='a'&&ch<='z') a[++x]=ch,ch=getchar();
	while (ch<'a'||ch>'z') ch=getchar();
	x=0;
	while (ch>='a'&&ch<='z') b[++x]=ch,ch=getchar();
	for (int i=1;i<=n;++i)
		for (int j=1;j<=m;++j)
			for (int k=1;k<=kk;++k)
			{
				if (a[i]==b[j]) f[i][j][k][1]=max(f[i-1][j-1][k-1][0],f[i-1][j-1][k][1])+1;
				f[i][j][k][0]=max(max(max(f[i-1][j-1][k][0],f[i-1][j-1][k][0]),max(f[i][j-1][k][0],f[i][j-1][k][1])),max(f[i-1][j][k][0],f[i-1][j][k][1]));
			}
	for (int i=1;i<=kk;++i)
		ans=max(max(f[n][m][i][1],f[n][m][i][0]),ans);
	printf("%d\n",ans);
	return 0;
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值