Codeforces Round #547 D. Colored Boots

15 篇文章 1 订阅

题目传送门

D. Colored Boots
题目描述
There are nn left boots and nn right boots. Each boot has a color which is denoted as a lowercase Latin letter or a question mark (’?’). Thus, you are given two strings ll and rr, both of length nn. The character lili stands for the color of the ii-th left boot and the character riri stands for the color of the ii-th right boot.A lowercase Latin letter denotes a specific color, but the question mark (’?’) denotes an indefinite color. Two specific colors are compatible if they are exactly the same. An indefinite color is compatible with any (specific or indefinite) color.For example, the following pairs of colors are compatible: (‘f’, ‘f’), (’?’, ‘z’), (‘a’, ‘?’) and (’?’, ‘?’). The following pairs of colors are not compatible: (‘f’, ‘g’) and (‘a’, ‘z’).Compute the maximum number of pairs of boots such that there is one left and one right boot in a pair and their colors are compatible.Print the maximum number of such pairs and the pairs themselves. A boot can be part of at most one pair.
输入
The first line contains nn (1≤n≤1500001≤n≤150000), denoting the number of boots for each leg (i.e. the number of left boots and the number of right boots).The second line contains the string ll of length nn. It contains only lowercase Latin letters or question marks. The ii-th character stands for the color of the ii-th left boot.The third line contains the string rr of length nn. It contains only lowercase Latin letters or question marks. The ii-th character stands for the color of the ii-th right boot.
输出
Print kk — the maximum number of compatible left-right pairs of boots, i.e. pairs consisting of one left and one right boot which have compatible colors.The following kk lines should contain pairs aj,bjaj,bj (1≤aj,bj≤n1≤aj,bj≤n). The jj-th of these lines should contain the index ajaj of the left boot in the jj-th pair and index bjbj of the right boot in the jj-th pair. All the numbers ajaj should be distinct (unique), all the numbers bjbj should be distinct (unique).If there are many optimal answers, print any of them.

input :
10
codeforces
dodivthree
output:
5
7 8
4 9
2 2
9 10
3 1
input:
7
abaca?b
zabbbcc
output :
5
6 5
2 3
4 6
7 4
1 2
input :
9
bambarbia
hellocode
output :
0
input :
10
code???
???test
output:
10
6 2
1 6
7 3
3 5
4 8
9 7
5 1
2 4
10 9
8 10

题目解释:
  • 这道题输入两个字符串( 由26个英文字母和?组成) ,两个字符串如果字母相同就可以匹配,?可以和任何值匹配,先输出最大匹配的个数 K ,在之后 K 行输出 i j ( i 为该字符在第一个串中的位置,j 为该字符在第二个字符串中的位置)。
解题:
  • 这道一开始用数组去写,越写越乱,开了6个数组,写加改做了一小时,最后一个样例都没过,于是改用队列做,一下思路清晰多了,很快就过了。果然用合适的方法才行。
  • 这道题思路不难,保存串后,先将非?的都匹配了,再用?去匹配,注意先与非?的字符去匹配,这样不浪费?。
  • 具体就是用int 型队列 l [ t - ‘a’ ] , r [ t - ‘a’ ] 保存第一个串各个字母字符的位置,将?的位置保存在队列 lw 中。再输入第二个串中的字符,如果 l [ t - ’ a ’ ] 不为空说明 1串中有可以匹配的值,将两个字符对应位置保存在数组 b[ ] 中,保存后就将他们都从对应的队列中弹出,记录匹配数量的值 ans ++。
  • 再从头遍历队列,如果保存第二个串的?的队列不为空说明还能匹配,就保存第一个串中队首值和这个?再2串中的位置。匹配完2串的?后,用相同的方法处理1串中的?。
  • 这样操作下来有可能还有?没有匹配,就将?相互匹配,不断保存两个队首元素。
  • 输出即可。
完整代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MA=1e6+2;
struct anss
{
    int x,y;
}b[MA];
queue<int>l[30],r[30];
queue<int>lw,rw;
int main()
{
    int n;
    char t;
    cin>>n;
    for(int i=1;i<=n;++i){
        cin>>t;
        if(t!='?'){
            l[t-'a'].push(i);
        }
        else{
            lw.push(i);
        }
    }
    int ans=0;
    for(int j=1;j<=n;++j){//输入2串的同时去与1串看能否匹配。
        cin>>t;
        if(t!='?'){
            if(!l[t-'a'].empty()){
                ans++;
                b[ans].x=l[t-'a'].front();
                b[ans].y=j;
                l[t-'a'].pop();
            }
            else{
                r[t-'a'].push(j);
            }
        }
        else{
            rw.push(j);
        }
    }
    for(int i=0;i<26;++i){//处理2串中的?
        if(rw.empty())break;
        while(!l[i].empty()&&!rw.empty()){
            ans++;
            b[ans].x=l[i].front();
            l[i].pop();
            b[ans].y=rw.front();
            rw.pop();
        }
    }
    for(int j=0;j<26;++j){//处理1串中的?
        if(lw.empty())break;
        while(!r[j].empty()&&!lw.empty()){
            ans++;
            b[ans].y=r[j].front();
            r[j].pop();
            b[ans].x=lw.front();
            lw.pop();
        }
    }
    while(!lw.empty()&&!rw.empty()){//处理最后剩下的还未匹配的?
        ans++;
        b[ans].x=lw.front();
        lw.pop();
        b[ans].y=rw.front();
        rw.pop();
    }
    printf("%d\n",ans);
    for(int i=1;i<=ans;++i){
        printf("%d %d\n",b[i].x,b[i].y);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值