CodeForces

题目链接http://codeforces.com/problemset/problem/589/A

题目大意:给定n个邮件地址,任何电子邮件地址都将显示为“login @ domain”,其中:

1.a“login”是一个由非空的小写和大写字母序列以及点('.')和加号('+')组成的序列,从字母开始;
2.a“domain”是一个由非空的小写和大写字母和点组成的序列,因为点将序列分成非空单词,仅由字母组成(即“domain”从字母开始,以字母结尾,不包含两个或多个连续点)。

比较邮件地址时,不考虑字符的大小写。此外,在比较bmail.com地址时,服务器会忽略登录中的点以及电子邮件地址登录部分中第一个字符“加”(“+”)到字符“at”(“@”)的所有字符。

在给定n个邮件地址后,让你输出每个邮件地址出现的次数与所有这个邮箱的原始串。

例:

输入:

6
ICPC.@bmail.com
p+con+test@BMAIL.COM
P@bmail.com
a@bmail.com.ru
I.cpc@Bmail.Com
a+b@bmail.com.ru

输出:

4
2 ICPC.@bmail.com I.cpc@Bmail.Com
2 p+con+test@BMAIL.COM P@bmail.com
1 a@bmail.com.ru
1 a+b@bmail.com.ru

解题思路:题目有点长,理解题目理解了老半天。题目好像没有涉及什么算法,不过对代码能力好像要求还是有点的,看了别人的代码才好不容易码出来了。。。做法大概就是直接定义一个结构体数组,用来存储每个字符串的原字符串和忽略那些不必要的变形之后的字符串,以及存储他们所在的位置下标。先排序将变形后相同的字符串排在相邻的位置,然后将变形后相同的字符串的下标存到一个ans向量组里,向量的大小即为该字符串相同的数量。输出时再将结构体数组排成初始顺序即可。

附上代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<vector>
 6 using namespace std;
 7 struct node{
 8     string s;  //存储原字符串 
 9     string change;  //存储改变之后的字符串 
10     int id;  //存储位置下标 
11 }st[20005];
12 vector<int> ans[20005];  //相同字符串的下标存在同一个向量里面 
13 int n;
14 
15 bool comp(const node &a,const node &b)
16 { //相同的字符串排在一起 
17     if(a.change==b.change)
18         return a.id<b.id;
19     return a.change<b.change;
20 }
21 
22 bool comp1(const node &a,const node &b)
23 {  //恢复成它们的初始位置 
24     return a.id<b.id;
25 }
26 int main()
27 {
28     while(cin>>n)
29     {
30         for(int i=0;i<n;i++)
31         {
32             cin>>st[i].s;
33             st[i].id=i;
34             ans[i].clear();
35         }
36         for(int i=0;i<n;i++)
37         {
38             string temp;
39             if(st[i].s.size()>=10)
40             {
41                 temp=st[i].s.substr(st[i].s.size()-10,10);  //如果字符串长度大于10则取出后10位字符,判断是否为"@bmail.com" 
42                 for(int j=0;j<10;j++)
43                     temp[j]=towlower(temp[j]);  //将temp转换成小写 
44                 //cout<<temp<<endl;
45             }
46             if(temp=="@bmail.com")//判断该字符串后10位是否为"@bmail.com" 
47             {
48                 bool ok=false,ok1=false;
49                 for(int j=0;j<st[i].s.size();j++)
50                 {
51                     if(st[i].s[j]=='@') ok=false,ok1=true;
52                     if(st[i].s[j]=='+') ok=true;
53                     if((st[i].s[j]=='.'&&!ok1)||ok) continue;  //在第一个“+”至“@”内的不计 
54                     st[i].change.push_back(towlower(st[i].s[j]));  //转换成小写 
55                 }
56             }
57             else  //普通邮件地址,直接转换成小写
58             {
59                 for(int j=0;j<st[i].s.size();j++)
60                     st[i].change.push_back(towlower(st[i].s[j]));   
61             }
62         }
63         sort(st,st+n,comp);
64         int cnt=0;
65         ans[0].push_back(st[0].id);
66         for(int i=1;i<n;i++)  //比较字符串是否相同,相同的下标放到同一个向量 
67         {
68             if(st[i].change==st[i-1].change) ans[cnt].push_back(st[i].id);
69             else ans[++cnt].push_back(st[i].id); 
70         }
71         sort(st,st+n,comp1);
72         cout<<cnt+1<<endl;
73         for(int i=0;i<=cnt;i++)
74         {
75             cout<<ans[i].size();  //向量的大小即为该相同字符串的数量 
76             for(int j=0;j<ans[i].size();j++)
77                 cout<<" "<<st[ans[i][j]].s;
78             cout<<endl;
79         }
80     }
81     return 0;
82 }
原文地址:https://www.cnblogs.com/zjl192628928/p/9402494.html