HDU1298 非常好的题 字典树+DFS

题意:
模拟手机打字的猜想功能,根据概率,每按一个按键,输出可能性最高的串。先给定N个单词,以及频率,就是每个单词中字母的频率,比如:“hell,3”和“hello ,4”,则前缀相同时,h的频率为4+3=7。
题解:
https://www.cnblogs.com/A-way/archive/2012/11/22/2783176.html
这是我这道题看的博客。
这道题的整洁是字典树+DFS,之前我就想到是字典树,然后因为要输出很多时间段的形态,那么肯定是需要递归遍历的,但是我想不到怎么递归遍历,而我看了大佬的博客才知道,我一直在想的递归遍历其实是深搜,
突然感觉自己的想法好弱,难道是因为一遇到不会的题就百度导致的原因吗?缺乏那种思维与算法搭桥的灵动性,哎,另外深搜也很久没怎么练习过了,感觉就算能想出深搜我也写不出来,哎。
写深搜的时候老是磕磕碰碰,错这错那,从来没有一次是通顺的过去的,突然感觉自己得找时间锻炼一下自己的灵动性了,而不仅仅是拓展自己的知识面。
当我放弃了继续深入想这道题的时候说明我已经又失去了一次与好题较量提升思维的能力了,看了答案之后懊悔不已,总感觉自己应该能想出来自己所想到的递归已经往dfs靠拢,但是又感觉自己这榆木脑子实在难于往算法上靠拢,为自己失去做一次好题感到悲哀,明明学习算法就是为了更好的实现自己脑海里的一些想法难以实现的东西,可是我却始终依赖不了算法。

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
struct node
{
    int p;
    node *next[26];
    node(){
        p=0;
        for(int i=0;i<26;i++)
        next[i]=0;
    }
}*root;
int phone[8][4]={{0,1,2},{3,4,5},{6,7,8},{9,10,11},{12,13,14},{15,16,17,18},{19,20,21},{22,23,24,25}};
int re[8]={3,3,3,3,3,4,3,4};
int q;
char End[107],ans[107];//end在杭电哪里编译会出错的,要改成End 
char c[107];
void insert(char *s,int k)
{
    node *r=root;
    for(int i=0;s[i];i++)
    {
        int x=s[i]-'a';
        if(r->next[x]==0) r->next[x]=new(node);
        r=r->next[x];
        r->p+=k;
    }
}
void dfs(node *r,int k,int len)
{
    if(k==len)
    {
        if(r->p>q)
        {
            q=r->p;
            for(int i=0;i<k;i++)
            End[i]=ans[i]+'a';
            End[k]='\0';
        }
        return ;
    }
    int x=c[k]-'2';
    for(int i=0;i<re[x];i++)
    {
        int t=phone[x][i];
        if(r->next[t])
        {
            ans[k]=t;
            dfs(r->next[t],k+1,len);
            ans[k]=0;
        }
    }
}
void del(node *head)
{
    for(int i=0;i<26;i++)
    if(head->next[i])
    del(head->next[i]);
    delete(head);
}
int main()
{
    int t,k=1,n,m,p;
    char s[107];
    scanf("%d",&t);
    while(t--)
    {
        root=new(node);
        scanf("%d",&n);
        for(int i=0;i<n;i++)
        {
            scanf("%s%d",s,&p);
            insert(s,p); 
        }
        printf("Scenario #%d:\n",k++);
        scanf("%d",&m);
        for(int i=0;i<m;i++)
        {
            scanf("%s",c);
            int len=strlen(c)-1;
            for(int i=0;i<len;i++)
            {

                q=0;
                dfs(root,0,i+1);
                if(q)
                printf("%s\n",End);
                else
                printf("MANUALLY\n");
            }
            printf("\n");
        }
        printf("\n");
        del(root);
    } 
}

/*
之前我就想到是字典树,然后因为要输出很多时间段的形态,那么肯定是需要递归遍历的,但是我想不到怎么递归遍历,而我看了大佬的博客才知道,我一直在想的递归遍历其实是深搜,
突然感觉自己的想法好弱,难道是因为一遇到不会的题就百度导致的原因吗?缺乏那种思维与算法搭桥的灵动性,哎,另外深搜也很久没怎么练习过了,感觉就算能想出深搜我也写不出来,哎。
写深搜的时候老是磕磕碰碰,错这错那,从来没有一次是通顺的过去的,突然感觉自己得找时间锻炼一下自己的灵动性了,而不仅仅是拓展自己的知识面。 
*/ 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章