这是一个类似于查字典的问题。已知一本“字典”中包含了一些英文单词(5000个左右,单词长度为1~12位),又已知一种对应关系,数字2~9共对应除去Q和Z的24个英文字母,每个数字可对应3个英文字母,如2可对应A,B,C,也就是说A,B,C均可用2表示。那给你一个n位的数字,这个数字可以表示的单词就有3^n种。现题目给定一个1~12位长的数字,要求输出在字典中存在的这个数字所对应成的所有单词。
由于字典中包含的单词数量不多,我们可以先将单词读入内存,然后一一比较。但这种做法肯定不是最好的,如果单词的个数很多的话,那肯定花的时间会增大,这种方法必须把每个字典里的每个单词都比较一次。
想到用哈希查找的方法,可以以数字为关键字key,f=key%5000作为哈希函数,定义数组arr[5000],将关键字为key的单词全都存到以arr[f]为头结点的链表中,这样的话每次查询都可以直接定址到key%5000,大大减少查询时间。写了好久,最后终于通过了。
/*
ID: whutzha1
PROG: namenum
LANG: C++
*/
#include<fstream>
using namespace std;
ifstream cin("namenum.in");
ifstream fin("dict.txt");
ofstream cout("namenum.out");
struct Node
{
char name[13];
long long num;
Node *next;
};
int main()
{
Node *arr[5000];
int i;
for (i=0;i<5000;i++)
{
arr[i]=NULL;
}
//读dict.txt文件
char read_name[13];
long long read_num;
int area;
int n;
char ch;
while(fin.get(ch))
{
for (i=0;i<13;i++)
{
while(ch==' '||ch=='\n')
{ fin.get(ch); }
read_name[i]=ch;
fin.get(ch);
if (ch==' '||ch=='\n')
break;
}
read_name[i+1]='\0';
read_num=0;
for(i=0;i<12;i++)
{
switch(read_name[i])
{
case 'A':
case 'B':
case 'C': n=2;break;
case 'D':
case 'E':
case 'F': n=3;break;
case 'G':
case 'H':
case 'I': n=4;break;
case 'J':
case 'K':
case 'L': n=5;break;
case 'M':
case 'N':
case 'O': n=6;break;
case 'P':
case 'R':
case 'S': n=7;break;
case 'T':
case 'U':
case 'V': n=8;break;
case 'W':
case 'X':
case 'Y': n=9;break;
default: break;
}
read_num=(read_num*10+n);
if (i==11||read_name[i+1]=='\0')
{
area=read_num%5000;
Node *p=(Node *)malloc(sizeof(Node));
if (arr[area]==NULL)
{
arr[area]=p;
}
else
{
Node *q=arr[area];
Node *r;
while (q)
{
r=q;
q=q->next;
}
r->next=p;
}
p->num=read_num;
p->next=NULL;
for (i=0;i<13;i++)
{
p->name[i]=read_name[i];
if (p->name[i]=='\0')
{
break;
}
}
break;
}
}
}//while
long long num;
bool flag;
cin>>num;
Node *p;
p=arr[num%5000];
flag=false;
while(p)
{
if (p->num==num)
{
flag=true;
// for(i=0;i<12;i++)
// {
// cout<<p->name[i];
// if (p->name[i+1]=='\0')
// {cout<<endl;break;}
// }
cout<<p->name<<endl;
}
p=p->next;
}
if (!flag) {cout<<"NONE"<<endl;}
return 0;
}