USACO Name That Number (dfs+字典树)

题目大意: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;
}

 

posted @ 2012-07-22 20:49  BeatLJ  阅读(305)  评论(1编辑  收藏  举报