题意:给定一个字符串 t ,然后再给出一系列字符串 a ,对于 t 中子串于 a 相同的可以染上颜色,问把 t 全部染上颜色至少用几次
因为字串和源字符串数据量都很小,所以只用暴力在 t 中找出所有的对应覆盖区间,然后做一遍区间覆盖贪心即可。当时场上很快就想到了做法,但是写代码bebug能力太差了,改了两个小时都没改出来
#include<bits/stdc++.h>
#define debug1(a) cout<<#a<<'='<< a << endl;
#define debug2(a,b) cout<<#a<<" = "<<a<<" "<<#b<<" = "<<b<<endl;
#define debug3(a,b,c) cout<<#a<<" = "<<a<<" "<<#b<<" = "<<b<<" "<<#c<<" = "<<c<<endl;
#define debug4(a,b,c,d) cout<<#a<<" = "<<a<<" "<<#b<<" = "<<b<<" "<<#c<<" = "<<c<<" "<<#d<<" = "<<d<<endl;
#define debug5(a,b,c,d,e) cout<<#a<<" = "<<a<<" "<<#b<<" = "<<b<<" "<<#c<<" = "<<c<<" "<<#d<<" = "<<d<<" "<<#e<<" = "<<e<<endl;
#define debug0(x) cout << "debug0: " << x << endl
#define fr(t, i, n) for (int i = t; i < n; i++)
#define fi first
#define se second
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
typedef pair<LL,LL> PLL;
struct PIIi{
int fi,se;
int id;
bool operator ==(const PIIi&a)const{
return fi == a.fi && se == a.se && id == a.id;
}
};
bool st[1000];
vector<PIIi> edge;
void solve(){
string t;cin >> t;
int n;cin >> n;
string kmp;
edge.clear();
fr(0,i,n){
cin >> kmp;
int m = kmp.size();
for(int j = 0;j <= t.size();j ++){
if(t.substr(j,m) == kmp)
{
edge.emplace_back(PIIi{j,j+m,i});//末尾多的也行
//debug2(j,j+m);
}
}
}
sort(edge.begin(),edge.end(),[](PIIi a,PIIi b){
return a.fi < b.fi || a.fi == b.fi && a.se > b.se;
});
//edge.erase(unique(edge.begin(),edge.end()),edge.end());
/*memset(st,0,sizeof st);//判断有无解
for(int i = 0;i < edge.size();i ++)
{
for(int j = edge[i].fi;j < edge[i].se;j ++)st[j] = true;
}
for(int i = 0;i <= n;i ++)if(!st[i])
{
cout << -1 << endl;
return ;
}
*/
int start = 0,idx = 0,ed = t.size();
bool cover = 0;
vector<PII> ans;
for(int i = 0;i < edge.size();)
{
int j = i,r = -1e9,idk = 0;
while(j < edge.size() && edge[j].fi <= start)
{
if(edge[j].se > r)
{
r = edge[j].se;
idx = edge[j].id;
idk = edge[j].fi;
}
j ++;
}
if(r < start)break;
ans.emplace_back(PII{idx,idk});
start = r;
i = j;
if(r == t.size())
{
cover = 1;
break;
}
}
//ans.push_back(PII{idx,cl}),step++;
if(!cover)
{
cout << -1 << endl;
return;
}
cout << ans.size() << endl;
for(auto x:ans)cout << x.fi+1 << " " << x.se+1 << endl;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int T = 1;cin >> T;
while(T--){
solve();
}
return 0;
}
区间覆盖的模板是在已覆盖区间内找伸出外面最长的,同时注意处理边界
因为这个题目的数据量很小,所以一开始我就想先把所有区间能覆盖的进行判断,如果还有未覆盖成功的区间就不用贪心这个步骤了,可以减少代码量和思维量。
但是显然判断全区间是否被覆盖写错了,把 t 的长度用成了 n ,导致mle
这个故事告诉我们,代码变量名不要瞎起orz