洛谷P1245 电话号码

题目描述
电话机上每一个数字下面都写了若干个英文字母。分布如下:

1~abc

2~def

3~ghi

4~jkl

5~mn 6~opq

7~rst

8~uvw

9~xyz

现在给定一个单词表和一串数字密码,请你用单词表中的单词翻译这个密码。

输入格式
第一行为一个正整数N表示单词表中单词的个数(N≤100);

第二行为一个长度不超过100的数字串,表示密码;

接下来的N行,每行一个长度不超过20的单词,表示单词表。

输出格式
仅一行,表示翻译后的原文,如果密码无法翻译,则输出“No Solutions!”,如果密码有多种翻译方式,则输出任意一种即可。

输入输出样例
输入 #1复制
8
73373711664
thi
shs
this
is
b
a
boo
k
输出 #1复制
thi shs b boo k
说明/提示
仅一行,表示翻译后的原文,如果密码无法翻译,则输出“No Solutions!”,如果密码有多种翻译方式,则输出任意一种即可。

由@zhouyonglong提供SPJ
上代码:

#include<cstdio>
#include<cstdlib>
#include "memory.h"
#define MAXN 110
using namespace std;
const char st[26]={1,1,1,2,2,2,3,3,3,4,4,4,5,5,6,6,6,7,7,7,8,8,8,9,9,9};
struct trie
{
  int end;
  trie *son[17];
  inline trie();
}mmp[MAXN*MAXN],*mtp=mmp,*head=NULL;
char str[MAXN][MAXN],a[MAXN],b[MAXN];
int ans[MAXN],cnt=0,n=0;
inline void read(int&);
void write(const int&);
inline void insert(char*,const int&);
inline void init(char*);
void dfs(int);
inline void out();
int main()
{
  register int i=0;
  head=++mtp;
  scanf("%d",&n);
  scanf("%s",a);
  for(i=0;a[i];a[i++]^=48);
  for(i=1;i<=n;++i)
  {
    scanf("%s",str[i]);
  }
  for(i=1;i<=n;++i)
  {
    init(str[i]);
    if(*b)insert(b,i);
  }
  dfs(0);
  printf("No Solutions!");
  return 0;
}
inline trie::trie()
{
  end=0;
  memset(son,0,sizeof(son));
  return;
}
inline void out()
{
  register int i=0;
  for(i=1;i<cnt;++i)
  {
    printf("%s ",str[ans[i]]);
  }
  printf("%s",str[ans[cnt]]);
  exit(0);
}
void dfs(int x)
{
  register trie *p=head;
  for(;a[x];)
  {
    if(p->end)
    {
      ans[++cnt]=p->end;
      dfs(x);
      --cnt;
    }
    if(p->son[a[x]])
    {
      p=p->son[a[x]];
      ++x;
    }
    else
    {
      return;
    }
  }
  if(p->end)
  {
    ans[++cnt]=p->end;
    out();
  }
  return;
}
inline void init(char *a)
{
  register int i=0;
  for(;*a;++i,++a)
  {
    b[i]=st[*a-'a'];
  }
  b[i]='\0';
  return;
}
inline void insert(char *a,const int &id)
{
  register trie *p=head;
  for(;*a;++a)
  {
    if(p->son[*a])
    {
      p=p->son[*a];
    }
    else
    {
      p=p->son[*a]=++mtp;
    }
  }
  p->end=id;
  return;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值