题目大意:
要求构造一个长度为 n n n 的字符串,有 k k k 个限制条件 ( k ≤ 20 ) (k \le 20) (k≤20),每个限制需保证长度为 x x x 的前缀中的所有子串去重后恰好有 c c c 个回文串。
思路:
- 不难发现对于每一个限制来说,每次要求字符串长度增加 l e n len len, 回文串的数量不能比 l e n len len 增加的还多,可以先找出无解的情况
- 依次看每一个限制,如果当前还差的长度 > 当前还差的回文串数量,可以直接用abcabc去接上,回文串数量不会增加;如果当前还差的长度 = 当前还差的回文串数量时,直接构造类似
dddddd
的相同字母形式,长度为当前还差的回文串数量,因为限制数不超过20个,所以要保证字母不重复即可
代码:
#include <bits/stdc++.h>
#define all(x) x.begin(),x.end()
using namespace std;
const int N = 2e5 + 10, mod = 1e9 + 7;
const double eps = 1e-6;
typedef long long LL;
typedef pair<int,int> PII;
using ARR = array<int, 3>;
void solve() {
int n,k;
cin >> n >> k;
vector<int> x(k),c(k);
for(int i = 0; i < k; i++) cin >> x[i];
for(int i = 0; i < k; i++) cin >> c[i];
if (c[0] > x[0]) {
cout << "NO\n";
return;
}
for(int i = 1; i < k; i++){
if(x[i] - x[i - 1] < c[i] - c[i - 1]){
cout << "NO\n";
return;
}
}
cout << "YES\n";
string s = "abc";
char now = 'c';
int res = 3;
for (int i = 0; i < k; i++) {
while (x[i] - s.size() > c[i] - res) {
now ++;
if(now == 'd') now = 'a';
s += now;
}
while (s.size() < x[i]) {
s += 'd' + i;
res++;
}
}
cout << s << "\n";
}
signed main() {
cin.tie(nullptr)->ios_base::sync_with_stdio(false);
cout.tie(nullptr);
int T = 1;
cin >> T;
for (;T--;) solve();
}