予鈴

アウトプットとメモ書きの中間みたいな記事がたくさん出ます。

C. String Transformation 1

Problem

You are given two string  s and  tof the length of N.
You can perform following operation :
1.selects some subset of positions  p_1,p_2,....p_k of  s such that  A_{p_i} = A_{pj}, 1 \leq i,j \leq k

2.selects a letter y > A_{p_k}, and sets each letter in positions  p_1,p_2,....p_k, to letter y

Minimize the number of operation to make equal to s and t.
if you can not, print -1.

Solution

・大きい文字にしか置き換えられないので、s_i > t_iとなるときは明らかに-1.
・subsetを選ぶというのが厄介なので、操作を言い換えることができれば良さそう.
例えば、 s中に含まれるアルファベット cについて、
 \{u\, |\, 1 < i < N , s_{i} = c\} とすると、 c \rightarrow t_{u_i} 置き換える操作が考えられる。
ここで、どのようなt_{u_i}を選ぶべきなのか悩むが、できるだけ大きいt_{u_i}を選べば良さそう。
※ここもうちょっと足す
・イメージとしては、大きい cから見ていって、変換先を先に投げる感じ(?)

#include<bits/stdc++.h>
using namespace std;
using ll = long long;
#define int ll
#define rep(i,n) for(int i=0;i<n;i++)
#define all(in) in.begin(), in.end()
using pii = pair<int,int>;
void fast_io(){ios::sync_with_stdio(false); cin.tie(nullptr);}
inline int solve(){
    int N; cin >> N;
    string s,t; cin >> s >> t;
    rep(i,N){
        if(s[i] > t[i]){
            cout << -1 << endl; return 0;
        }
    }
    vector<vector<int>>v(21);
    rep(i,N){
        if(t[i] == s[i])continue;
        v[t[i] - 'a'].push_back(s[i] - 'a');
    }
    int ans = 0;
    priority_queue<pii,vector<pii>>que;
    for(int i = 20; i >= 0;--i){
        sort(all(v[i]),greater<>());
        for(auto& e : v[i]) que.emplace(i,e);
        if(que.empty())continue;;
        if(que.top().first == i){
            ++ans;
            auto tp = que.top();
            while(not que.empty() && que.top() == tp){
                que.pop();
            }
            while(not que.empty() && que.top().first == i){
                auto tt = que.top(); que.pop();
                tt.first = tp.second;
                que.push(tt);
            }
        }
    }
    ans += que.size();
    cout << ans << endl;
    return 0;
}
signed main(){
    fast_io();
    int Q = 1;
    cin >> Q;
    while(Q--){solve();}
}