题目来自Codeforce 1141Dhttp://codeforces.com/problemset/problem/1141/D
因为是全英文题面,就先简单的阐述一下题面。
首先输入一个数n,然后输入两个长度为n的字符串,我们需要做的就是对两个字符串的每个字符从1到n编号,然后对两个字符串的所有字符进行一对一的匹配,如果两个字符串中有字符相同,则匹配成功,输出两个字符的对应编号,其中?可以和任意字符匹配,问最多能匹配多少个字符,输出最优解。
解题思路
这个题如果直接遍历不用说,肯定超时,但是像我这种菜鸡其他的也不会,所以我也是遍历,但是可以说一种优化过的遍历。
首先我用的是结构体来存这两个字符串,这样的话可以保证字符在排序之后也可以和它的编号对应,然后就是对这两个字符串进行从大到小的排序,这样就把?全部放到了最后,只要对前面的字母先对应匹配,再来处理?,就会省不少时间,并且因为前面的字母都是已经排过序的,匹配起来也非常好处理,多余的操作很少,速度自然也就快了。其中我还用了两个bool数组分别对应两个字符串的所有字符,一旦某一个字符被匹配过之后,就利用bool数组对其进行标记,减少后面的处理步骤。cun数组就是用来存放对应的编号的。
完整代码
#include<iostream> #include<algorithm> using namespace std; struct stu { int num; char str; }; stu a[150001],b[150001]; int cun[150001][2]; bool cmp(stu n,stu m) { return n.str>m.str; } bool str1[150001],str2[150001]; int main() { int i,j,k=1; int n,sum=0; cin>>n; for(i=1;i<=n;i++) { cin>>a[i].str; a[i].num=i; } for(i=1;i<=n;i++) { cin>>b[i].str; b[i].num=i; } sort(a+1,a+n+1,cmp); sort(b+1,b+n+1,cmp); i=1; j=1; while(1) { if(a[i].str=='?'||b[j].str=='?'||i>n||j>n) break; if(a[i].str==b[j].str) { sum++; cun[sum][0]=a[i].num; cun[sum][1]=b[j].num; str1[a[i].num]=true; str2[b[j].num]=true; i++; j++; } else if(a[i].str>b[j].str) { while(i<=n) { i++; if(a[i].str<=b[j].str) break; } } else if(a[i].str<b[j].str) { while(j<=n) { j++; if(a[i].str>=b[j].str) break; } } } //cout<<i<<" "<<j<<endl; while(i<=n&&k<=n) { if(str2[b[k].num]) { k++; continue; } if(a[i].str=='?'&&!str1[a[i].num]) { sum++; cun[sum][0]=a[i].num; cun[sum][1]=b[k].num; str2[b[k].num]=true; str1[a[i].num]=true; k++; } i++; //cout<<i<<" "<<k<<endl; } k=1; while(j<=n&&k<=n) { if(str1[a[k].num]) { k++; continue; } if(b[j].str=='?'&&!str2[b[j].num]) { sum++; cun[sum][0]=a[k].num; cun[sum][1]=b[j].num; str1[a[k].num]=true; str2[b[j].num]=true; k++; } j++; //cout<<j<<" "<<k<<endl; } cout<<sum<<endl; for(k=1;k<=sum;k++) cout<<cun[k][0]<<" "<<cun[k][1]<<endl; return 0; }