【POJ 1451 T9】字典树(Trie树)

POJ1451
本题题意比较有意思,大概就是模拟手机输入法,先给你一个用户的词库,即每个单词出现的次数,这个时候再按照九键输入法给你一个数字序列,问你在输入这个序列的过程中,出现的字符串顺序,也就是对于每个数字序列,给出一个最有可能出现的字符串。
这道题我的做法比较巧妙,但是不怎么会算复杂度,还是很快的过去了。首先我们考虑,对于每个数字序列,我们都可以用一个string去映射,这样我们可以用一个map来离线保存每个数字序列对应的最有可能出现的字符串,可是我们怎么知道每个数字序列最有可能出现的字符串是哪个呢,首先我们对单词进行映射,把每个单词映射成数字序列,然后在插入的过程中,对于每一个前缀都更新一下这个前缀对应的map,最后查询的时候就可以直接输出了。
POJ1451代码

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<sstream>
#include<map>
using namespace std;
const int maxn =2e6+5;
int tree[maxn][30];
int sum[maxn];
int tot;
int belong[30];
map<string,int> mm;//每种数字序列最大出现次数
map<string,string>mm2;//每种序列对应的最大次数的字符串
void insert_(char *str,int num)
{
   int len=strlen(str);
   int root=0;
   string strr="";
   string str2="";
   for(int i=0;i<len;i++)
   {
       int id=str[i]-'a';
       strr+=(belong[id]+'0');//将插入的字符串映射成数字序列
       str2+=str[i];//当前前缀
       if(!tree[root][id]) tree[root][id]=++tot;
       root=tree[root][id];
       sum[root]+=num;//统计每个前缀出现次数
       if(mm[strr]<sum[root])//更新map
       {
           mm[strr]=sum[root];
           mm2[strr]=str2;
       }
   }
   return ;
}
char ss[maxn];
void init()//数字与字母间的映射
{
    for(int i=0;i<25;i++)
    {
        if(i<18)
            belong[i]=2+i/3;
        else
            belong[i]=2+(i-1)/3;
    }
    belong[25]=9;
    return ;
}
int main()
{
    init();
    int cnt=1;
    int n,m,t,num;
    scanf("%d",&t);
    while(t--)
    {
        mm.clear();
        mm2.clear();
        scanf("%d",&n);
        while(n--)
        {
            scanf("%s%d",ss,&num);
            insert_(ss,num);
        }
        scanf("%d",&m);
        printf("Scenario #%d:\n",cnt++);
        while(m--)
        {
            scanf("%s",ss);
            string tmp="";
            int len=strlen(ss);
            for(int i=0;i<len-1;i++)
            {
                tmp+=ss[i];//对于每个前缀直接输出
                if(!mm2.count(tmp)) printf("MANUALLY\n");
                else printf("%s\n",mm2[tmp].c_str());
            }
            printf("\n");
        }
        for(int i=0;i<tot;i++)
        {
           sum[i]=0;
            for(int j=0;j<30;j++)
                tree[i][j]=0;
        }
        printf("\n");
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_38891827/article/details/80672991