洛谷· [ZJOI2013]丽洁体

博客围绕仿写体作品展开,金先生研究形如“A*B*C”的体作品,因数据量大请人帮忙去掉尽量少的单词使其成指定体。介绍了输入输出格式、样例及数据规模,题解采用贪心算法,让A尽量靠左、C尽量靠右,为B找最优解,时间复杂度可过。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

初见安~这里是传送门:洛谷P3333

题目描述

平时的练习和考试中,我们经常会碰上这样的题:命题人给出一个例句,要我们类比着写句子。这种往往被称为仿写的题,不单单出现在小学生的考试中,也有时会出现在中考中。许多同学都喜欢做这种题,因为较其它题显得有趣。仿写的句子往往具有“A__B__C”的形式,其中A,B,C是给定的由一个或多个单词组成的短句,空的部分需要学生填写。当然,考试的时候空在那里也是可以的。例如,“其实天不暗阴云终要散,其实 ,其实 ,其实路不远一切会如愿,艰难困苦的日子里我为你祈祷,请你保重每一天”。再比如,“见了大海的汹涌,没见过大山的巍峨,真是遗憾;见了大山的巍峨,没见过 ,还是遗憾。出发吧,永远出发。 ,人有不老的心情。”

由于现在是网络时代,我们不再只能仿写命题人命的题,我们可以仿写网上各种句子和段落。2011年3月26日,某人在博客上发布了的消息就惹来了很多人的仿写。

很难过吧。。。考得完爆了。。。

。。。。。。其实也没什么可以说的。。。都是蒟蒻的借口罢了。。。

。。。自己果然还只是半吊子水平呢。。。。

。。。祝大家都能进省队。。。其实只要不要有遗憾就好了呢。。。

虽然我很遗憾或许不能走下去了。。。。。

886

在网络上广泛流传的仿写,因为在某些地方有独到之处,大都被命名为“某某体”。打开人人,刷新微博,你也能发现这样和那样的体,比如,对不起体,**说明他爱你体等等。金先生注意到了这一现象,他敏锐地认为这是一个很有价值的研究课题,于是就其展开研究,打算发一篇paper。由于在网上发消息,人们有了更大的灵活度,人们有时因为表达的需要,还往原本固定的A, B, C中添加一些修饰的词语。这就给辨别一个句子或段落是否是另一个句子或段落的仿写增加了困难。

金先生现在研究一种形如“A*B*C”的体作品,其中A, B, C分别是某个由若干单词组成的短句,*代表0个或多个单词。他在网上找了大量的体作品,不过很多体作品不太合乎原作者的格式,也就是相当于在正规的体作品中插入了0个或多个单词。

由于数据量太大,金先生无法一个一个看过去,于是想请你帮忙,去掉尽量少的单词,使它成为指定的体。

输入格式:

包含4行。

第一行是某个也许不规范的体作品T,

接下来三行分别代表A, B, C。

输出格式:

仅一行,包含一个数,即最少的去除单词数。

输入样例#1: 

xiang yao yi zhi ai zhe mou wu de hua yi yao guai zhi si lai shuo tai chang le xiang yao shi xian yi qie meng xiang de hua yi ren lei zhi sheng lai shuo tai duan le
yao
tai chang le yao
tai duan le

输出样例#1: 

2

说明

【样例说明】

在上述样例中,不规范的体作品为:“想要一直爱着某物的话,以妖怪之死来说太长了;想要实现一切梦想的话,以人类之生来说太短了”。

规范的体形如:“要*太长了要*太短了”。

修改后的规范的体为:“要一直爱着某物的话,以妖怪之死来说太长了;要实现一切梦想的话,以人类之生来说太短了”。

【数据规模与约定】

对于20%的数据,1≤|T|, |A|, |B|, |C|≤10。 对于40%的数据,1≤|T|, |A|, |B|, |C|≤100。 对于70%的数据,1≤|T|, |A|, |B|, |C|≤1000。 对于100%的数据,1≤|T|, |A|, |B|, |C|≤50000;所有单词长度不超过5,出现次数不超过500;数据保证答案总存在。

题解:

众所周知——神犇WJMZBMR在Day1差点跌出省队线后在烦恼中写下了这句话,然后Day2就AK了……

进入正题。

这个题其实是很好暴力的。因为要形如A*B*C,那么我们最后要山区的单词就是:A前面的,C后面的部分和A、B、C三个串里面的部分

就比如:若A = “happy end”,而原字符串中有这么一句:“happy smile in the end”,那么其中的“smile in the”三个单词都是我们要删去的。

我们就贪心——让句子A尽量靠左,句子C尽量靠右。因为要去掉的部分一定是从原句头到句子A最右端的位置减去句子A的长度,C同理。而且这样一来也可以让B有足够的空间来找到最优解——让B内部的其他单词尽量少。

因为题目保证了每个单词最多出现500次,我们大不了就为了B找500次!并且同AC的贪心原理,每找到一个可以作为B的开头的位置,就尽量靠前地往后找B的剩余部分,让B跨越的长度尽量短,最好是只有B的长度。

数据范围不大,所以时间复杂度是可以过的。

感觉这个题其实难在读入啊……

#include<bits/stdc++.h>
#define maxn 50005
using namespace std;
string s[maxn], a[maxn], b[maxn], c[maxn];
int ts = 0, ta = 0, tb = 0, tc = 0, tot = 0x3f3f3f3f, ans = 0;
int main() {
	do {cin >> s[++ts];} while(getchar() == ' ');//cin是不会读入空格的
	do {cin >> a[++ta];} while(getchar() == ' ');
	do {cin >> b[++tb];} while(getchar() == ' ');
	do {cin >> c[++tc];} while(getchar() == ' ');
	
	register int cnt = 1, l, r;
	for(int i = 1; i <= ts; i++) {//找A
		if(s[i] == a[cnt]) cnt++;
		if(cnt > ta) {l = i, ans += l - ta; break;}
	}
	cnt = tc;
	for(int i = ts; i > 0; i--) {//找C,因为尽量靠右所以倒着找
		if(s[i] == c[cnt]) cnt--;
		if(!cnt) {r = i, ans += ts - r + 1 - tc; break;}
	}
	
	for(int i = l + 1; i < r; i++)//注意l和r是不能取等的【l取等也过了……洛谷没有卡细节啊。
		if(s[i] == b[1]) {//可以作为B 的开始
			cnt = 1;
			for(register int j = i; j < r; j++) {//同A和C的套路找B
				if(s[j] == b[cnt]) cnt++;
				if(cnt > tb) {tot = min(tot, j - i + 1 - tb); break;}
			}
			
		}
		
	printf("%d\n", ans + tot);
	return 0;
}

迎评:)
——End——

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值