多重映射

题目: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;
}
posted @ 2024-03-09 16:55  黄金庭院第一码农樱  阅读(34)  评论(0)    收藏  举报