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;

}

 

你可能感兴趣的:(number)