ural1002(字典樹+dp)

題意:給你一些數字對應一些字母(一對多),然後給一個數字串和一些字母串,問數字串最少可由哪幾個字母串組成。
題解:將字母串對應的數字串插入字典樹。然後設dp[i]爲數字串第i個數字到最後一個數字最少能用幾個字母串構成,dp[i]=min(dp[j]),i+1<=j

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;

const int maxn=50005*50;
char str[105],s[50005][100];
int pre[105],num[105],dp[105],g[105],cnt;
int mp[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};
int n;
struct Trie{
    int trie[maxn][10];
    int val[maxn];
    int sz;
    Trie(){sz=1;memset(trie[0],0,sizeof trie[0]);}
    int idx(char c)
    {
        return mp[c-'a'];
    }
    void insert(char s[],int v)
    {
        int len=strlen(s);
        int u=0;
        for(int i=0;i<len;i++)
        {
            int id=idx(s[i]);
            if(trie[u][id]==0)
            {
                memset(trie[sz],0,sizeof trie[sz]);
                val[sz]=0;
                trie[u][id]=sz++;
            }
            u=trie[u][id];
        }
        val[u]=v;
    }
}e;
int main()
{
    while(scanf("%s",str))
    {
        if(str[0]=='-')break;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%s",s[i]);
            e.insert(s[i],i);
        }
        int len =strlen(str);
        for(int i=0;i<=len;i++)dp[i]=1e9;
        dp[len]=0;
        memset(pre,-1,sizeof pre);
        for(int i=len-1;i>=0;i--)
        {
            int u=0;
            for(int j=i;j<len;j++)
            {
                int id=str[j]-'0';
                if(e.trie[u][id]==0)break;
                u=e.trie[u][id];
                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]==1e9)printf("No solution.\n");
        else{
            cnt=0;
            int k=0;
            while(pre[k]!=-1)
            {
                g[cnt++]=num[k];
                k=pre[k];
            }
            for(int i=0;i<cnt;i++)
            {
                if(i==cnt-1)
                printf("%s\n",s[g[i]]);
                else printf("%s ",s[g[i]]);
            }
        }
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章