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);
    } 
}

/*
之前我就想到是字典樹,然後因爲要輸出很多時間段的形態,那麼肯定是需要遞歸遍歷的,但是我想不到怎麼遞歸遍歷,而我看了大佬的博客才知道,我一直在想的遞歸遍歷其實是深搜,
突然感覺自己的想法好弱,難道是因爲一遇到不會的題就百度導致的原因嗎?缺乏那種思維與算法搭橋的靈動性,哎,另外深搜也很久沒怎麼練習過了,感覺就算能想出深搜我也寫不出來,哎。
寫深搜的時候老是磕磕碰碰,錯這錯那,從來沒有一次是通順的過去的,突然感覺自己得找時間鍛鍊一下自己的靈動性了,而不僅僅是拓展自己的知識面。 
*/ 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章