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;
}
}