链接:http://codeforces.com/problemset/problem/1141/D
题意:给出一个n,接着给出两个长度为n的字符串,由?和小写字母组成,两个相同的小写字母可以
配成一副,?和任意的字母都可以配对,问这两个串互相配对,最多多少组,输出任意的配对方案;
因为?是任意都可以的,所以可以先枚举26个小写字母,将能通过字母配对的进行字母配对,最后再
消耗?来配对,若有剩余的?再进行配对;代码写的有点长,但都是ctrl c+ctrl v,四部分内容是一样的
加入位置信息用vector来实现,方便删减;
AC代码
#include<iostream>
#include<stdio.h>
#include<string>
#include<map>
#include<algorithm>
#include<set>
#include<vector>
using namespace std;
struct node{
int cnt;
vector<int>v;
}u[27], v[27];
set<pair<int, int>>s;
int main(){
int n;
string a, b;
cin >> n >> a >> b;
for (int i = 0; i < n; i++) //存入字母和?的信息
{
if (a[i] == '?')
{
u[26].cnt++;
u[26].v.push_back(i + 1);
}
else
{
u[a[i] - 'a'].cnt++;
u[a[i] - 'a'].v.push_back(i + 1);
}
}
for (int i = 0; i < n; i++)
{
if (b[i] == '?')
{
v[26].cnt++;
v[26].v.push_back(i + 1);
}
else
{
v[b[i] - 'a'].cnt++;
v[b[i] - 'a'].v.push_back(i + 1);
}
}
int cnt = 0;
for (char i = 'a'; i <= 'z'; i++) //字母与字母的配对
{
int num1 = u[i - 'a'].cnt, num2 = v[i - 'a'].cnt;
int MIN = min(num1, num2);
u[i - 'a'].cnt -= MIN;
v[i - 'a'].cnt -= MIN;
while (MIN--)
{
cnt++;
s.insert({ u[i - 'a'].v.back(), v[i - 'a'].v.back() });
u[i - 'a'].v.pop_back(), v[i - 'a'].v.pop_back();
}
}
for (char i = 'a'; i <= 'z'; i++) //字母与?的配对
{
int MIN = min(u[26].cnt, v[i - 'a'].cnt);
u[26].cnt -= MIN;
v[i - 'a'].cnt -= MIN;
while (MIN--)
{
cnt++;
s.insert({ u[26].v.back(), v[i - 'a'].v.back() });
u[26].v.pop_back(), v[i - 'a'].v.pop_back();
}
MIN = min(v[26].cnt, u[i - 'a'].cnt);
v[26].cnt -= MIN;
u[i - 'a'].cnt -= MIN;
while (MIN--)
{
cnt++;
s.insert({ u[i - 'a'].v.back(), v[26].v.back() });
u[i - 'a'].v.pop_back(), v[26].v.pop_back();
}
}
int MIN = min(v[26].cnt, u[26].cnt);
while (MIN--) //?与?的配对
{
cnt++;
s.insert({ u[26].v.back(), v[26].v.back() });
u[26].v.pop_back(), v[26].v.pop_back();
}
cout << cnt << endl;
for (auto i = s.begin(); i != s.end(); i++)
cout << i->first << " " << i->second << endl;
return 0;
}