您的位置:首页 > 其它

USACO Name That Number (dfs+字典树)

2012-07-22 20:49 337 查看
题目大意:2到9每个数字对应3字母(对应关系题中已给出),给定一个长度不超过12的数字序列,则可以对应到多个字符串,现给定一个字典(含很多字符串的文件),打印数字序列对应的且在字典中出现过的字符串。

分析:每个数字对应3个字母,最坏情况下有12个数字,可对应312=531441个字符串,而且题中字典中的字符串是按字典序给出的,所以可以用二分查找,所以应该可以用暴力+二分过。另一个办法就是建字典树,然后dfs时边搜遍判断,这样效率应该有所提升。我是用字典树过的。

需要注意的是当字典中不存在符合要求的字符串时,要输出“NONE”

View Code

/*
ID: lijian42
LANG: C++
TASK: namenum
*/
#include <stdio.h>
#include <string.h>
#define N 5001
#define LEN 15
int node;
int next[N*LEN][26];
bool isend[N*LEN];
int n;
char num[LEN];
char name[LEN];
char table[10][3];
bool success;
void add(int cur,int k)
{
memset(next[node],0,sizeof(next[node]));
isend[node]=false;
next[cur][k]=node++;
}
void build()
{
FILE *fp=fopen("dict.txt","r");

int i,k,cur;
char s[LEN];
node=1;
memset(next[0],0,sizeof(next[0]));
while(~fscanf(fp,"%s",s))
{
cur=0;
for(i=0;s[i];i++)
{
k=s[i]-'A';
if(next[cur][k]==0) add(cur,k);
cur=next[cur][k];
}
isend[cur]=true;
}
}
void init()
{
int i,j;
char c='A';
for(i=2;i<10;i++)
{
for(j=0;j<3;j++)
{
table[i][j]=c;
c++;
if(c=='Q')  c++;
}
}
build();
}
void dfs(int dep,int cur)
{
if(dep==n)
{
name[dep]=0;
if(isend[cur]) puts(name),success=true;
return;
}
int i=num[dep]-'0',j,k;
for(j=0;j<3;j++)
{
k=table[i][j]-'A';
if(next[cur][k]==0) continue;
name[dep]=k+'A';
dfs(dep+1,next[cur][k]);
}
}
int main()
{
freopen("namenum.in","r",stdin);
freopen("namenum.out","w",stdout);
init();
while(~scanf("%s",num))
{
n=strlen(num);
success=false;
dfs(0,0);
if(success==false)  puts("NONE");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: