1029练习题 B 从头再来
KONO题面哒!
问题描述
WX2004作为一个非酋,玩什么都必须要用人海战术来堆死对面。这天他打开GFL,发现自己因为太菜太非被YM降级了。他对自己太菜这个事实感到十分懊悔,于是准备改过自新。他统计了自己以前拥有的人形和现在拥有的人形,并把他们按星级用字母编号,然后用一种不可描述的玄学方法排序得到了两个字符串s,t。现在他正在编队去打核心8,。由于他又菜又非,他只好把自己所拥有的人形(即t序列)按顺序分出k个组和铁血车轮战。但他太想念被降级之前的队伍,于是要求这k个队伍的字符串都能在原人形(即s序列)中找到并且顺序相同。现在他已经因抽不到陈自闭了,请你来帮他算出自己能塞多少个人形进队伍。
(注:按星级用字母编号即用a,b,c……来代替1,2,3……。由于此时的GFL经过了数次更新,所以不只有6个星级,有26个。)
(题目大意:从s,t中选出k个不相交的连续的非空子串,保持每个子串在 s ,t中的相对位置顺序,使得每个相对的子串相同并求出所有子串长度和的最大值。给出的s,t中只有小写字母)
输入格式
第一行三个整数 n,m,k ,分别代表字符串 s,t 的长度,选出的子串的个数。
第二行一个字符串 s .
第三行一个字符串 t .输出格式
一行一个整数,表示选出的子串长度之和的最大值。
样例输入
15 9 4
ababaaabbaaaabb
bbaababbb
样例输出
8
数据范围
\(n,m ≤ 1000,k ≤ 10\)
第一眼动归。然后我就打炸了。最后我交了个搜索,Wa0。
动归思路:
- 状态:\(F[i][j][l][s]\)表示s序列中取到i号位,t序列中取到j号位,现在取了l组人形,第i,j号人选不选(0为必须选,1为可选可不选)
- 状态转移方程:
-
- \(s[i]!=t[j]\):\(f[i][j][l][1]=max(f[i-1][j][l][1],f[i][j-1][l][1])\)(都可选可不选并不能开新组,把上一个状态赋值过来)
-
- \(s[i]=t[j]\):\(f[i][j][l][0]=f[i-1][j-1][l-1][1]+1\)(可以开新组)
-
-
- 若此时:\(s[i-1]=t[j-1]\):\(f[i][j][l][0]=max(f[i][j][l][0],f[i-1][j-1][l][0]+1)\)(不开新组)
-
-
-
- 判断完上一个条件后,\(f[i][j][l][1]=max(f[i][j][l][0],max(f[i-1][j][l][1],f[i][j-1][l][1]))\)(一般通过转移)
(应该算是很好理解了吧……)
- 判断完上一个条件后,\(f[i][j][l][1]=max(f[i][j][l][0],max(f[i-1][j][l][1],f[i][j-1][l][1]))\)(一般通过转移)
-
KONO代码哒!
#include<cstdio>
#include<iostream>
#include<cmath>
using namespace std;
int n,m,k;
char tmp[1010];
int f[1010][1010][11][2];
int a[1010],b[1010];
int main()
{
scanf("%d%d%d",&n,&m,&k);
int l,i,j;
scanf("%s",tmp);
for(i=1;i<=n;i++)a[i]=tmp[i-1]-'a';
scanf("%s",tmp);
for(i=1;i<=m;i++)b[i]=tmp[i-1]-'a';
for(l=1;l<=k;l++)
{
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
if(a[i]==b[j]){
f[i][j][l][0]=f[i-1][j-1][l-1][1]+1;
if(a[i-1]==b[j-1]){
f[i][j][l][0]=max(f[i][j][l][0],f[i-1][j-1][l][0]+1);
}
f[i][j][l][1]=max(f[i][j][l][0],max(f[i-1][j][l][1],f[i][j-1][l][1]));
}
else f[i][j][l][1]=max(f[i-1][j][l][1],f[i][j-1][l][1]);
}
}
}
printf("%d\n",f[n][m][k][1]);
}
瞎改题面.jpg
原文地址:https://www.cnblogs.com/cooper233/p/11768172.html
时间: 2024-10-16 16:51:33