ps:要是有更好,更新颖的方法,欢迎分享
【法一:单纯用map】
#include <iostream>
#include <map>
#include <vector>
#include <algorithm>
#include <sstream>
using namespace std;
struct FFri{
int num;string phone[100];
};
struct Fri{
string name;int num;string phone[100];
};
bool cmp1(const Fri& left,const Fri& right)
{
if(left.name!=right.name)return left.name<right.name;return true;
}
bool cmp2(const string& left,const string& right)
{
if(left.length()!=right.length())return left.length()<right.length();return left<right;
}
int main()
{
int n;cin>>n;map<string,FFri> per;while(n--){
string name;cin>>name;int num;cin>>num;for(int i=0;i<num;i++){
string p;int flag =0;cin>>p;for(int j=0;j<per[name].num;j++){
if(p==per[name].phone[j])//判断现要存的号码是否已存 {
flag=1;break;}else//未存,判断是否为已存的后缀 {
string str= per[name].phone[j]; if(p.length()<str.length()&&str.substr(str.length()-p.length())==p)// 为已存后缀,不需要再存 {
flag=1;break;}else if(str.length()<p.length()&&p.substr(p.length()-str.length())==str)//已存的号码为现存的后缀,把已存的号码更新为现存的 {
per[name].phone[j]=p;flag=1;break;}} }if(flag==0) {
per[name].phone[per[name].num]=p;per[name].num++;}}}vector<Fri> f;for(map<string,FFri>::iterator it=per.begin();it!=per.end();it++){
Fri tmp;tmp.name=it->first;tmp.num=it->second.num;for(int i=0;i<tmp.num;i++){
tmp.phone[i]=it->second.phone[i];}f.push_back(tmp);}sort(f.begin(),f.end(),cmp1);//按照朋友名字排序 for(int i=0;i<(int)f.size();i++){
sort(f[i].phone,f[i].phone+f[i].num,cmp2);//每个朋友的电话号码排序 }cout<<f.size()<<endl;for(int i=0;i<(int)f.size();i++){
cout<<f[i].name<<" "<<f[i].num<<" ";for(int j=0;j<f[i].num;j++)cout<<f[i].phone[j]<<" ";cout<<endl;}
}
ps:(1)下面是错了最后五个数据的后缀函数,最开始犯的错误我没有想到用sustr(),而是选择用find来查找后缀,错误的原因就是:如果长的号码不仅中间包含短的号码,后面还包含短的号码,查找到的是中间的那个,会被误判不为同一个号码。
举个栗子:01212 12
len1=5, len2=2, 01212=find(12)=1, 1+2!=5,就被判为12不是01212的后缀
(2)还有一个越界的错误,就是电话号码的数组开少了,一旦号码超过10个,就不行了
【法二:用map和set去重】
#include <iostream>
#include <vector>
#include <set>
#include <map>
#include <algorithm>
using namespace std;
bool cmp(const string& left,const string& right)
{
if(left.length()!=right.length())return left.length()<right.length();return left<right;
}
int main(){
int n;cin>>n;map<string,set<string>> per;while(n--){
string name;cin>>name;int num;cin>>num;while(num--) {
string p;//电话号码cin>>p;per[name].insert(p); //先将相同的电话号码去掉 }}cout<<per.size()<<endl;for(map<string,set<string>>::iterator itm=per.begin();itm!=per.end();itm++)//遍历每个不同的人 {
vector<string> phone;phone.clear();for(set<string>::iterator it1=itm->second.begin();it1!=itm->second.end();it1++)//遍历这个人的所有号码 {
string tmp1=*it1;int flag=0;for(set<string>::iterator it2=itm->second.begin();it2!=itm->second.end();it2++)//查找这个人号码里时候含有是后缀的号码 {
string tmp2=*it2;if(tmp1==tmp2)continue;if(tmp1.length()<tmp2.length()&&tmp2.substr(tmp2.length()-tmp1.length())==tmp1)//判断tmp1是否是tmp2的后缀 {
flag=1;break;}}if(flag==0)phone.push_back(tmp1);}sort(phone.begin(),phone.end(),cmp);cout<<itm->first<<" "<<phone.size()<<" ";for(int i=0;i<(int)phone.size();i++)cout<<phone[i]<<" ";cout<<endl;}
}