Search for a command to run...
Progressive hints first, then the full explanation and implementation when you're ready to cash out.
Review status
AI-generated and still unreviewed. Double-check the details before internalizing them.
Hints
Open only as much as you need to keep the solve alive.
First check the boring but deadly condition: if t does not contain every character of s enough times, the answer is Impossible. No ordering trick can create letters out of vibes.
Think of the final string being built from left to right. At any moment you have already matched some prefix s[0..pos-1] as a subsequence. The only future requirement is to still be able to match s[pos..] using the remaining letters.
For each suffix of s, precompute how many of each letter it still needs. Then a candidate next character is allowed iff, after removing it from the remaining multiset and possibly advancing pos, the remaining multiset still covers that suffix need.
Now greedily try letters 'a' through 'z' at every output position. Pick the first letter whose use keeps the state feasible. This works because lexicographic order only cares about the first position where two strings differ.
When the chosen character equals s[pos], you should advance pos. Matching it never hurts: it reduces the future requirement by exactly that character, and delaying the match only makes life harder for no lexicographic benefit.
We need rearrange all letters of t, and somewhere inside that rearranged string, s must appear as a subsequence.
The key phrase is subsequence, not substring. The letters of s do not need to be adjacent, but they must appear in order.
A tempting wrong move is to just sort t. Sorting gives the smallest possible string with no restrictions, but it might destroy the required order of s. Cheap string, invalid answer. Sad trombone.
So the real problem is:
Build the lexicographically smallest permutation of the multiset of letters in
t, while guaranteeing that a left-to-right scan can match all ofs.
If t does not even contain the required letters of s, print Impossible. That part is non-negotiable.
The Greedy View
Suppose we are building the answer from left to right.
Let pos be how much of s we have already matched. So s[0..pos-1] is already matched, and we still need to match the suffix s[pos..].
At some step, we want to place the smallest possible next character. A character ch is valid if, after using it, it is still possible to complete the remaining suffix of s from the letters we have left.
That is exactly the kind of check greedy needs.
For example, if pos = 3, then the future still needs all letters from s[3..], with multiplicity. If the remaining multiset does not cover those needed counts, we are cooked.
Why Matching Immediately Is Correct
If the next chosen character equals s[pos], we advance pos.
Could it ever be better to treat that character as “extra” and not match it?
No. Matching it immediately consumes the same character either way, but reduces the future required suffix. That cannot make the situation worse. Delaying the match is just doing mental gymnastics to end up with fewer options.
So the state transition is simple:
chpos < |s| and ch == s[pos], increment poss[pos..]Fast Feasibility Checks
There are only 26 lowercase letters, so we can store counts in arrays of size 26.
Precompute:
Then, after a possible move to state pos, the remaining letters are feasible iff:
for every character c.
Since there are only 26 letters, checking this is cheap.
Greedy Algorithm
For each output position:
ch = 'a' to 'z'.ch is unavailable, skip it.s[newPos..] as a subsequence.ch is forced into the answer.Because lexicographic order is decided at the first differing position, picking the smallest valid next character is always optimal. Any smaller invalid character would make it impossible to finish, so it is fake cheapness.
Correctness Proof
First, the impossibility check is correct. If some letter appears more times in s than in t, then no permutation of t can contain s as a subsequence, because every matched character must come from t. Conversely, if all counts are sufficient, at least one valid arrangement exists: place s itself, then place all leftover letters anywhere.
Now consider one step of the greedy construction. Assume the already-built prefix is fixed and validly extendable, and pos is the length of the prefix of s already matched by this prefix.
The algorithm tries letters in increasing order and chooses the first one that leaves enough remaining letters to match s[pos..] after the transition. Therefore, after choosing this letter, at least one valid completion exists.
Every smaller letter was tested and rejected. Rejection means that after placing it, the remaining multiset cannot cover the still-unmatched suffix of s, so no valid full answer can start with the current prefix plus that smaller letter.
Thus the chosen letter is the smallest possible next character among all valid completions. Repeating this at every position gives the lexicographically smallest valid string.
Finally, whenever the chosen letter equals the next needed character of s, advancing pos is safe because it only decreases the future subsequence requirement.
Therefore, the algorithm is correct.
Complexity
For each output character, we try at most 26 letters, and each feasibility check scans 26 counts.
So the complexity is:
which is easily fine for . Memory is for suffix counts.
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
int main() {
setIO();
int T;
cin >> T;
while (T--) {
string s, t;
cin >> s >> t;
int m = (int)s.size();
vector<array<int, 26>> need(m + 1);
need[m].fill(0);
for (int i = m - 1; i >= 0; --i) {
need[i] = need[i + 1];
need[i][s[i] - 'a']++;
}
array<int, 26> rem{};
rem.fill(0);
for (char c : t) rem[c - 'a']++;
bool ok = true;
for (int c = 0; c < 26; ++c) {
if (rem[c] < need[0][c]) ok = false;
}
if (!ok) {
cout << "Impossible\n";
continue;
}
string ans;
int pos = 0;
int n = (int)t.size();
auto feasible = [&](int p) {
for (int c = 0; c < 26; ++c) {
if (rem[c] < need[p][c]) return false;
}
return true;
};
for (int i = 0; i < n; ++i) {
for (int c = 0; c < 26; ++c) {
if (rem[c] == 0) continue;
rem[c]--;
int nextPos = pos;
if (nextPos < m && c == s[nextPos] - 'a') nextPos++;
if (feasible(nextPos)) {
ans.push_back(char('a' + c));
pos = nextPos;
break;
}
rem[c]++;
}
}
cout << ans << '\n';
}
return 0;
}#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
int main() {
setIO();
int T;
cin >> T;
while (T--) {
string s, t;
cin >> s >> t;
int m = (int)s.size();
vector<array<int, 26>> need(m + 1);
need[m].fill(0);
for (int i = m - 1; i >= 0; --i) {
need[i] = need[i + 1];
need[i][s[i] - 'a']++;
}
array<int, 26> rem{};
rem.fill(0);
for (char c : t) rem[c - 'a']++;
bool ok = true;
for (int c = 0; c < 26; ++c) {
if (rem[c] < need[0][c]) ok = false;
}
if (!ok) {
cout << "Impossible\n";
continue;
}
string ans;
int pos = 0;
int n = (int)t.size();
auto feasible = [&](int p) {
for (int c = 0; c < 26; ++c) {
if (rem[c] < need[p][c]) return false;
}
return true;
};
for (int i = 0; i < n; ++i) {
for (int c = 0; c < 26; ++c) {
if (rem[c] == 0) continue;
rem[c]--;
int nextPos = pos;
if (nextPos < m && c == s[nextPos] - 'a') nextPos++;
if (feasible(nextPos)) {
ans.push_back(char('a' + c));
pos = nextPos;
break;
}
rem[c]++;
}
}
cout << ans << '\n';
}
return 0;
}