2022 Aug 18 刷题log

本文记录了三道算法题的解题思路,涉及区间覆盖的转换与优化,数组成本最小化问题的线性公式分解,以及同余数组调整策略。通过对例子的观察和分析,提炼了解题的关键点,包括动态规划的应用和性质比较。
摘要由CSDN通过智能技术生成

        CF 811D  Color with Occurrences

问:给一个string s,和 n个substring ai,求最少数量的substring覆盖s

转换字符串覆盖问题 -> 区间覆盖问题

区间覆盖

        1. 按左边界升序排

        2. 在 左边界 小于/等于/等于+1 当前右边界里,选右边界最远的

当s的长度短,可以使用 数组 做区间覆盖

        ri 代表从 si开始可以覆盖到的最远右边界

规定左右边界协议 和 下标

        左闭右开 or 左闭右闭,0-index or 1-index

学习

        1.  s.substr(开始, substr长度)

        2. s.length() 要 cast 到 int,不然会 RE

        3. max_element()  左闭右开                        

总结

          1. 转换字符串覆盖问题 -> 区间覆盖问题

          2.  pair区间覆盖 和 数组区间覆盖   

          3.  规定左右边界 和 下标协议

#include <iostream>
#include <algorithm>
#include <cstring>
#include <map>
#include <vector>
#include <utility>
using namespace std;
 
/* 
1
bababa
2
ba
aba
*/
void solve(){
	string s; cin>>s;
	int n; cin>>n;
	//0 index, 左闭右开
	int r[105]; 
	int id[105];
	memset(r, 0, sizeof(r));
	for(int i=0;i<n;i++){
		string sb; cin>>sb;
		//应该是 小于等于
		for(int j=0;j<=(int)s.length()-(int)sb.length();j++){
			//substr(开始, substr的长度)
			if(s.substr(j, sb.length())==sb){
				//开始 + 长度 超 1
				//r[j] in
				//左闭右闭 [l, r]
				if(j+sb.length() > r[j]){
					r[j]=j+sb.length();
					id[j]=i;
				}
			}
		}
	}
	// for(int i=0;i<s.length();i++){
	// 	cout<<r[i]<<" ";
	// }
	int end=0;
	vector<pair<int, int> > ans;
	while(end<s.length()) {
		//max_element 左闭右开 [r, l)
		int next_end=max_element(r, r+end+1)-r;
		if(r[next_end] <= end){ 
			cout<<-1<<endl;
			return;
		}
		ans.push_back({id[next_end], next_end});
		end=r[next_end];
	}	
	cout<<ans.size()<<endl;
	for(int i=0;i<ans.size();i++){
		cout<<ans[i].first+1<<" "<<ans[i].second+1<<endl;
	}	
}
int main(){
	int t; cin>>t;
	while(t--){
		solve();
	}
}

------------------------------------------------

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值