Color with Occurrences
题意:
有一个text t, 和n个字符串\(s_1, s_2, s_3, \cdots, s_n\),在一种操作中可以选择其中的一个\(s_i\), \(s_i\)是t的子串,将t中这个位置的字符串进行染色,你要把整个t字符串都染色,并且已经染色的字符串染了色之后还是红色,如果不可以输出-1,如果可以输出,最少需要几步,并且输出每一步用的\(s_i\)的i, 和在第几个位置进行染色
思路:
观察数据范围很小,所以可以直接暴力找到每个\(s_i\), 能够在t中的能够染色的区间,将他们按照l从小到大的顺序,l相同r从小到大的顺序进行排序,排序序后就转为求最小区间覆盖问题,最小区间覆盖问题,只要先把初始0位置取最优,后面的就是不断的贪在符合条件的范围内r最大的,如果r到达了右端点直接跳出,如果最后r没有到达右端点直接 -1
总结:
小范围暴力,染色而且是可以重复的那就相当于区间覆盖问题,要求操作次数最少,那就是最少区间覆盖问题
点击查看代码
#include <bits/stdc++.h>
#define endl '\n'
#define IOS ios::sync_with_stdio(false);
using namespace std;
typedef long long ll;
#define PII pair<pair<ll, ll>, ll>
ll q, n;
string t, s;
struct Interval
{
ll l, r;
} region[210];
bool check(ll start, string s)
{
ll lent = t.size() - start;
ll lens = s.size();
if (lent < lens)
return false;
for (int i = start, j = 0; i < t.size() && j < s.size(); ++i, ++j)
{
if (t[i] != s[j])
return false;
}
return true;
}
bool comp(PII x, PII y)
{
if (x.first.first != y.first.first)
return x.first.first < y.first.first;
return x.first.second < y.first.second;
}
int main()
{
IOS; cin.tie(0), cout.tie(0);
cin >> q;
while (q--)
{
cin >> t;
cin >> n;
vector<PII> v;
for (int i = 1; i <= n; ++i)
{
cin >> s;
//看看s在t中可以覆盖的区间
for (int j = 0; j < t.size(); ++j)
{
if (check(j, s))
v.push_back({ {j, j + s.size() - 1}, i }); //前两个塞区间,后面塞位置
}
}
if (v.size() == 0)
{
cout << "-1" << endl;
continue;
}
sort(v.begin(), v.end(), comp);
if (v[0].first.first != 0)
{
cout << "-1" << endl;
continue;
}
int cnt = 0;
ll l = 1, r = 0;
int whatcnt = 0;
while (cnt < v.size() && v[cnt].first.first == 0) //先讨论l == 1的最大左边界,这个是必须要选的
{
if (r < v[cnt].first.second)
{
whatcnt = cnt;
r = max(r, v[cnt].first.second);
}
++cnt;
}
ll ans = 0;
region[++ans].l = v[whatcnt].second, region[ans].r = v[whatcnt].first.first;
bool flag = true;
for (int i = cnt; i < v.size(); ++i) //cnt这个点是还没有遍历过的
{
ll tempr = r;
if (tempr == t.size() - 1) //说明已经到最后了
{
break;
}
int j = i;
int whatj = i;
while (j < v.size() && v[j].first.first <= r + 1)
{
if (tempr < v[j].first.second)
{
whatj = j;
tempr = max(tempr, v[j].first.second);
}
++j;
}
if (j == i)
{
flag = false;
break;
}
i = j - 1;
r = max(r, tempr);
region[++ans].l = v[whatj].second, region[ans].r = v[whatj].first.first;
}
if (r < t.size() - 1 || flag == false) //特殊判断
{
cout << "-1" << endl;
continue;
}
cout << ans << endl;
for (int i = 1; i <= ans; ++i)
{
cout << region[i].l << " " << region[i].r + 1 << endl;
}
}
return 0;
}