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();
}
}
------------------------------------------------