多重對映

黄金庭院第一码农樱發表於2024-03-09

題目:AtCoder Beginner Contest 342_C
連結:https://atcoder.jp/contests/abc342
題意:
給出一串字串S,字串僅由小寫字母組成,有m次操作,第mi次操作的意思為將字串S中所有出現的字元C轉化為字元D,m次操作完成後輸出最終字串。
思路:
本題是一道非常標準的字元多重對映問題,僅需要用一個陣列ans將每一個字元對映後所對應的字元存下來即可。但由於是多重對映,因此我們需要考慮先後順序與字元覆蓋的問題。
如:
樣例1:a->b 與 樣例2:a->b
b->c b->c
a->d
對於樣例一應將a,b,c均輸出為c,而對於樣例二a轉化為的d,b轉化為了c。
對於已經轉化了的字元a,若轉化後的字元又繼續轉化,因將字元a一起轉化。由於本題的資料比較小,僅有26,因此可以在每次轉化時遍歷陣列ans,將每一個符合條件的字元轉換。
程式碼:

#include<bits/stdc++.h>
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)

using namespace std;

int add(int x, int y){return x ? add((x & y) << 1, x ^ y): y;}

#define ONLINE_JUDGE

int n,m;
string s;
char a[30];

int main()
{
#ifndef ONLINE_JUDGE
    freopen("1.in", "r", stdin);
    freopen("1.out", "w", stdout);
#endif
    ios;
    cin>>n;
    cin>>s;
    cin>>m;
    char x,y;
    for(char i='a';i<='z';i++)
    {
        a[i-'a'+1]=i;
    }
    for(int i=1;i<=m;i++)
    {
        cin>>x>>y;
        for(int j=1;j<=26;j++)
        {
            if(a[j]==x)
            {
                a[j]=y;
            }
        }
    }
    for(int i=0;i<n;i++)
    {
        cout<<a[s[i]-'a'+1];
    }
    cout<<"\n";
    return 0;
}

題目:牛客小白月賽88_E
連結:https://ac.nowcoder.com/acm/contest/75771/E
題意:
給出一個序列,函式M(x)=y表示將序列中的所有x轉換為y,m次操作,操作可以反覆疊加,輸出m次操作後的序列。
思路:
顯然該題的思路與做法與上面一題類似,用一張map去記錄轉化的值,但本題的資料大小為1e6,顯然按照上一題的做法直接遍歷肯定會TLE,需要換一種方法。
可以發現多重對映後可能存在多個原序列的值對應一個轉換後的值,但一個原序列的值不可能對應多個轉換後的值,每一次轉換都會將前一次轉換的值給覆蓋了。而我們不關心中間的轉換值是多少,僅需要輸出最終的轉換結果就好,因此可以將上一題的儲存方式反一下,用最終的轉化結果返回去找對應的原陣列。若原序列中的a轉換為b後又將b轉換為了c,就可以將c所對應的值中加上a,把b所對應的值中的a刪除
如:
a->b
c->b
b->d
對於這個樣例我們首先將a與c放入b所對應的陣列下標中,對於b->d將b所對應的值全部放入c中,然後將b的值清除即可。最終輸出答案時僅需要在轉換完成的陣列中查詢原序列值在哪裡即可。
程式碼:

#include<bits/stdc++.h>
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)

using namespace std;

int add(int x, int y){return x ? add((x & y) << 1, x ^ y): y;}

#define ONLINE_JUDGE

const int N=1e6+10;
int t,n,m;
int a[N];

int main()
{
#ifndef ONLINE_JUDGE
    freopen("1.in", "r", stdin);
    freopen("1.out", "w", stdout);
#endif
    ios;
    cin>>t;
    while(t--)
    {
        cin>>n>>m;
        map<int,int> ans;
        map<int,basic_string<int>> mp;
        for(int i=1;i<=n;i++)
        {
            cin>>a[i];
            ans[a[i]]=a[i];
            if(!mp.count(a[i]))
            {
                mp[a[i]]={a[i]};
            }
        }
        while(m--)
        {
            int x,y;
            cin>>y>>x;
            if(x==y)
            {
                continue;
            }
            mp[x];mp[y];
            if(mp[x].size()<mp[y].size())
            {
                mp[x].swap(mp[y]);
            }
            mp[x]+=mp[y];
            mp.erase(y);
        }
        for(auto [res,v] : mp)
        {
            for(auto i : v)
            {
                ans[i]=res;
            }
        }
        for(int i=1;i<=n;i++)
        {
            cout<<ans[a[i]]<<" ";
        }
        cout<<"\n";
    }

    return 0;
}

相關文章