现在的位置: 首页 > 综合 > 正文

ural 1002 Phone Numbers 字典树+dp

2017年07月12日 ⁄ 综合 ⁄ 共 1511字 ⁄ 字号 评论关闭

题意:

给定一串数字,问这串数字可能代表的单词,若存在多个可能,输出单词数最少的情况,若还是相同输出任意符合的单词。数字转换规则就是根据手机的按键规则。

题解:

我们将所有单词转换成数字,然后保存到字典树中。然后开始dp给定的数字串,dp[i]表示从i开始到最后的数字串最少需要多少个单词构成。dp[i]=min(dp[k+1])(m>k>=i,且[i,k]数字串在字典树中存在)。由于要输出单词,所以用pre[i]记录i位置的下个单词位置,num[i]记录i位置后的单词编号。

代码:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <queue>
#include <map>
#include <vector>
using namespace std;

#define LL long long
const int maxn=50001*51;
const int INF=1e8;
int f[27]={2,2,2,3,3,3,4,4,1,1,5,5,6,6,0,7,0,7,7,8,8,8,9,9,9,0};
struct Trie{
    int ch[maxn][10];
    int val[maxn];
    int sz;
    Trie(){sz=1;memset(ch[0],0,sizeof(ch[0]));}
    int idx(char c)
    {
        return f[c-'a'];
    }
    void insert(char *s,int v)
    {
        int i,u=0,n=strlen(s);
        for(i=0;i<n;i++)
        {
            int c=idx(s[i]);
            if(!ch[u][c])
            {
                memset(ch[sz],0,sizeof(ch[sz]));
                val[sz]=0;
                ch[u][c]=sz++;
            }
            u=ch[u][c];
        }
        val[u]=v;
    }
}e;
char a[50005][55];
char str[110];
int pre[110],num[110],dp[110],g[110],gg;
int main()
{
    while(scanf("%s",str)!=EOF)
    {
        if(str[0]=='-')break;
        int n;
        scanf("%d",&n);
        int i,j,k,u,m;
        memset(e.ch[0],0,sizeof(e.ch[0]));
        e.sz=1;
        for(i=1;i<=n;i++)
        {
            scanf("%s",a[i]);
            e.insert(a[i],i);
        }
        memset(pre,-1,sizeof(pre));
        m=strlen(str);
        dp[m]=0;
        for(i=0;i<m;i++)dp[i]=INF;
        for(i=m-1;i>=0;i--)
        {
            u=0;
            for(j=i;j<m;j++)
            {
                int c=str[j]-'0';
                if(!e.ch[u][c])break;
                u=e.ch[u][c];
                if(e.val[u])
                {
                    if(dp[i]>dp[j+1]+1)
                    {
                        dp[i]=dp[j+1]+1;
                        pre[i]=j+1;
                        num[i]=e.val[u];
                    }
                }
            }
        }
        if(dp[0]==INF)printf("No solution.\n");
        else
        {
            gg=0;
            k=0;
            while(pre[k]!=-1)
            {
                g[gg++]=num[k];
                k=pre[k];
            }
            for(i=0;i<gg;i++)
            {
                if(i==gg-1)printf("%s\n",a[g[i]]);
                else printf("%s ",a[g[i]]);
            }
        }
    }
    return 0;
}

/*
2
than
that
*/

抱歉!评论已关闭.