题目网址:http://poj.org/problem?id=1002
题目大意:
企业想拥有令人难忘的电话号码。要一个电话号码让人容易记住,方法之一是号码里面有一个难忘的单词或词组拼写。例如,您可以拨打TUT- GLOP拨打沃特卢大学。有时电话号码只有一部分是单词拼写。当你回到你的酒店,今晚你可以通过拨打310 - GINO吉诺订购比萨饼。另一种方法,设计的电话号码是一个难忘的方式分组数字。你可以通过拨打必胜客" 3个10 "的号码3-10-10-10 来订购比萨.
一个电话号码的标准形式是7个十进制数字用连字符之间的第三和第四位数字(如888-1200 ).一个电话的小键盘提供字母数字的映射,如下所示:
A,B和C映射到2
D,E和F映射到3
G, H和I映射到4
J,K,和L映射到5
M,N和O映射到6
P,R和S映射到7
T,U,和V映射到8
W,X,和Y映射到9的
没有包括字母Q和Z的映射,连字符不能拨号,可以根据需要添加和删除. TUT- GLOP的标准形式是888-4567, 310 - GINO的标准形式是310-4466 , 3-10-10-10的标准形式是310-1010 。两个电话号码是等价的,如果它们具有相同的标准形式.(他们拨打同一个号码。 )你的公司正在编制当地企业的电话号码目录。作为质量控制过程的一部分,你要检查,没有两个(或以上)的企业目录中的有相同的电话号码.
输入输入将包括一个案例。输入的第一行中指定的目录中的电话号码的数目(最多10万)作为单独行上的一个正整数.其余各行列出在目录中的电话号码,在单独一行的每个数字。每个电话号码的十进制数字,大写字母(不包括Q和Z )和连字符组成的字符串组成. 整整7个数字或字母的字符串中的字符.
产量
生成一行输出为每个电话号码,任何形式多次出现。该行应得到的标准形式的电话号码,后跟一个空格,其次是在电话号码出现在目录的次数。电话号码升字典顺序排列输出线。如果没有重复在输入打印线:
No duplicates.
测试数据:
Input
12
4873279
ITS-EASY
888-4567
3-10-10-10
888-GLOP
TUT-GLOP
967-11-11
310-GINO
F101010
888-1200
-4-8-7-3-2-7-9-
487-3279
Output
310-1010 2
487-3279 4
888-4567 3
我的解题思路:
先定义两个二维char数组 str1[][] 和str2[][] 其中str2[][]充当备用数组
①将全部电话号码都翻译成对应的数字,字母Ω转换成相应的数字字符f(Ω)=(Ω-65)/3+2+48 例如A对应于2 f(A)=(‘A’-65)/3+2+48 ==》2
如果字母Ω是'S' 'V' 'Y'中的任意一个,那么f(Ω)=(Ω-66)/3+2+48
转换后都存入str1[][]中
②消去每一个电话号码中的'-'并存入数组str2[][]中
③利用stdlib.h头文件中的qsort()将str2[][]按字典顺序从大到小排列
④用strcmp(str2[i],str2[i+1])去除重复项
我在解题过程中最初将str1[][]和str2[][]定义在main()函数中结果就直接编译不了了,后来我还是将str1[][]和str2[][]定义在main()函数中,将MAX开小一点就能编译了,提交上去之后一直超时。无奈之下在网上搜了一下,发现只要将大数组定义成函数外面的全局变量,这样就能编译了,我就再次把MAX开大一点,然后在外面定义str1[][]和str2[][]
再次提交之后就AC了,兴奋啊、、
还有一个小细节问题,可以利用memset()函数清空数组,我在调试的时候被str2[][]数组给坑惨了,因为每次上一次的结果都会影响到本次的str2[][]
memset(str2[i],0,sizeof(str2[i]));//清空str2[][]字符数组
代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 100000
char str1[MAX][50];
char str2[MAX][50];
int cmp(const void *a,const void *b)
{
char *ch1=(char *)a;
char *ch2=(char *)b;
return strcmp(ch1,ch2);
}
int main(int argc, char *argv[])
{
int n;
//char str1[MAX][50];
//char str2[MAX][50];
int i;
int j;
int k;
int sum;
int rk[MAX];
int flag;
while(scanf("%d",&n)!=EOF)
{
//getchar();
for(i=0;i<n;i++)
{
memset(str2[i],0,sizeof(str2[i]));//清空str2[][]字符数组
}
for(i=0;i<n;i++)
{
//gets(str1[i]); gets()函数自己的回车键对他人无影响,但是他人的回车键会对其本身造成影响
getchar();
scanf("%s",str1[i]);
for(j=0;str1[i][j]!='\0';j++)//将电话号码中的字母转换成对应的字符数字
{
if(str1[i][j]>='A'&&str1[i][j]<='Z')
{
if(str1[i][j]=='S'||str1[i][j]=='V'||str1[i][j]=='Y')
{
str1[i][j]=(char)((int)(str1[i][j]-66)/3+2+48);
}
else
{
str1[i][j]=(char)((int)(str1[i][j]-65)/3+2+48);
}
}
}
}
for(i=0;i<n;i++)//消去每一个电话号码的'-'并存入另一个二维字符数组str2[][]中
{
k=0;
for(j=0;str1[i][j]!='\0';j++)
{
if('-'!=str1[i][j])
{
str2[i][k]=str1[i][j];
k++;
rk[i]=k;
}
}
}
qsort(str2,n,sizeof(str2[0]),cmp);//将str2[][]中的电话号码按字典顺序从大到小排序
/*
测试:
printf("\n测试:\n");
for(i=0;i<n;i++)//测试
{
puts(str2[i]);
}
printf("\n\n");
*/
sum=1;
flag=0;
for(i=0;i<n-1;i++)//利用strcmp(str2[i],str2[i+1])消除重复项
{
if(!strcmp(str2[i],str2[i+1]))
{
sum++;
}
else if(sum>1)
{
for(j=0;j<rk[i];j++)
{
if(3==j)
{
printf("-");
}
printf("%c",str2[i][j]);
}
printf(" %d\n",sum);
sum=1;
flag=1;
}
}
if(!strcmp(str2[i],str2[i-1]))
{
if(sum>1)
{
for(j=0;j<rk[i];j++)
{
if(3==j)
{
printf("-");
}
printf("%c",str2[i][j]);
}
printf(" %d\n",sum);
flag=1;
}
}
if(!flag)
{
printf("No duplicates.\n");
}
}
return 0;
}