D. Color with Occurrences(Codeforces Round 811 (Div. 3))

40 篇文章 0 订阅
9 篇文章 0 订阅

https://codeforces.com/contest/1714/problem/D
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

题目大意

给定一个字符串 t t t 和一组字符串 s 1 , s 2 , … , s n s_1, s_2, \ldots, s_n s1,s2,,sn。每次操作可以选择其中一个字符串 s i s_i si,将 t t t 中所有 s i s_i si 的出现位置染成红色。求染成红色的最小次数以及染色方案。若无法将 t t t 中所有字符染成红色,输出 − 1 -1 1

思路分析

首先,我们要想到这是一道字符串的问题,需要用到字符串匹配。因为每次只能选择一个字符串染色,因此很自然的想到贪心策略。

p o s i pos_i posi 表示染色操作中选用了第 i i i 个字符串, c o l i col_i coli 表示染色操作中选用的 p o s i pos_i posi 所染的颜色为 i i i。用 c o l i [ j ] col_i[j] coli[j] 表示在第 j j j 次操作中,使用了第 i i i 个字符串,从位置 j j j 开始染色,如果没有使用第 i i i 个字符串,则 c o l i [ j ] col_i[j] coli[j] 0 0 0。对于每个字符 t i t_i ti,如果 t i t_i ti 没有被染色,则取 c o l i [ i ] col_i[i] coli[i] 的最大值,表示最后一次使用字符串 i i i 时,从位置 i i i 开始染色。

为了使染色的次数最小,需要从 c o l i [ i ] col_i[i] coli[i] 的最大值开始,往前遍历,直到最后一次出现位置,中途如果遇到已经染过色的字符,则直接跳过。在遍历的过程中,需要维护当前遍历到的位置 j j j,以及已经染色的字符的数量 c n t cnt cnt,如果 c n t = ∣ t ∣ cnt=|t| cnt=t,则表示所有字符均已染色,结束遍历。
AC代码:

#include<bits/stdc++.h>
using namespace std;
void solve(){
	string t;
	cin>>t; 
	int n;
	cin>>n;
	std::vector<std::string>s(n);
	for(int i=0;i<n;i++){
		cin>>s[i];
	} 
	int cnt=0;
	std::vector<std::array<int,2>> ans;
	while(cnt<int(t.length())){
		std::array <int,3>v{cnt,-1,-1};
		for(int i=0;i<n;i++){
			for(int j=0;j<=cnt&&j+s[i].length()<=t.length();j++){
				if(t.substr(j,s[i].length())==s[i]){
					v=max(v,array<int,3>{j+int(s[i].length()),i,j});
				}
			}
		}
		if(v[0]==cnt){
			cout<<"-1\n";
			return ;
		}
		cnt=v[0];
		ans.push_back({v[1],v[2]});
	}
	cout<<ans.size()<<"\n";
	for(auto[x,y]:ans){
		cout<<x+1<<" "<<y+1<<"\n";
	}
}
signed main(){
	int t;
	cin>>t;
	while(t--){
		solve();
	}
}
  
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值