题意:一个字符串 t,n 个子字符串,用子字符串给字符串 t 上色,求最小操作次数的方法。
思路:求出字符串 t 每个字符最长前缀下标 i, i 到当前字符能被子字符串上色。然后从结尾倒着一直往前跳就能求出答案。
代码:
#include<bits/stdc++.h>
#define pb push_back
#define all(x) x.begin(), x.end()
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int N = 2e5 + 10, P = 1e9 + 7, mod = 998244353;
PII pr[110];
int dp[110];
void solve(){
string t;
int n;
cin >> t >> n;
vector<string> s(n);
for(int i = 1; i <= t.size(); i++) dp[i] = 0x3f3f3f3f;
for(int i = 0; i < n; i++) cin >> s[i];
for(int i = 0; i < t.size(); i++){
for(int j = 0; j < n; j++)
if(i + s[j].size() <= t.size() && t.substr(i, s[j].size()) == s[j])
for(int k = 1; k <= s[j].size(); k++)
if(dp[i + k] > dp[i] + 1){
dp[i + k] = dp[i] + 1;
pr[i + k] = {i, j};
}
}
int l = t.size();
if(dp[l] == 0x3f3f3f3f){
cout << -1 << endl;
return;
}
vector<PII>v;
while(l > 0){
v.pb(pr[l]);
l = pr[l].first;
}
cout << v.size() << endl;
for(int i = 0; i < v.size(); i++)
cout << v[i].second + 1 << " " << v[i].first + 1 << endl;
}
int main(){
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int tt;
cin >> tt;
while(tt--) {
solve();
}
return 0;
}