4595. 【NOIP2016模拟7.8】String
Description&Data Constraint
有两种字符串 S,T。长度分别为 n,m。现在需要在 S 里面有序地选出 k 个子串,且在 T 中出现的顺序与这 k 个子串的顺序相同。问这k个子串最大的长度和。
n,m≤103,k≤10。
Solution
比较经典的 dp。
考虑 fi,j,k 表示 S 到了第 i 位,T 到了第 j 位,已经选择了 k 个子串的最大长度和。
但是由于当前位能否匹配与上一位有关,因此再开一维 0/1 表示 i−1 和 j−1 是否匹配。
转移:
如果 Si=Tj,说明当前位可以匹配,那么 fi,j,k,1=max。
然后 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}\}。
因为可以有空串,所以 ans=\max\{f_{n,m,1\texttt{->}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;
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步