动态建树加深搜之——模仿手机九键输入法

本文介绍了一种使用字典树解决POJ1451问题的方法,通过构建字典树并进行深度优先搜索来找出给定数字串对应的最高频词汇。详细解释了如何实现插入操作和搜索算法。

题目:poj1451

题意:给你一个词语出现次数的表,然后给你一个输入的数字串,每一步输出它最可能出现的单词。没有了就输出一个东西。

解答:建一个字典树,然后深度遍历这课树。每遍历一步都要记录下当前的字符串。最后输出。要记录当前位置最大值。如果该步没有更新过最大值说明这一步找不到字母了。

           用一个str数组记录当前的串。用k记录搜到多长了。注意回溯!还有,不管更新不更新答案,只要有就要继续往下搜。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string.h>
#include<cmath>
#include<stdlib.h>
using namespace std;
const int MAXN = 1010;
const int maxn = 110;
const int sonnum = 26,base = 'a';
int dir[11] = {0,0,0,3,6,9,12,15,19,22,26};
int Max[maxn];
char ans[maxn][maxn],str[maxn],numarr[maxn];
int n,m,k,p,len;
struct Trie
{
    int num;
    bool terminal;
    struct Trie *son[sonnum];
};
Trie *NewTrie()
{
    Trie *temp = new Trie;
    temp -> num = 1;
    for(int i = 0;i < sonnum;i++)
    {
        temp -> son[i] = NULL;
    }
    return temp;
}
void Insert(Trie *pnt,char *s,int a)
{
    Trie *tmp = pnt;
    int len1 = strlen(s);
    for(int i = 0;i < len1;i++)
    {
        if(tmp -> son[s[i]-base] == NULL)
        {
            tmp -> son[s[i]-base] = NewTrie();
            tmp -> son[s[i]-base] -> num += (a - 1);
        }
        else
            tmp -> son[s[i]-base] -> num += a;
        tmp = tmp -> son[s[i]-base];
    }
}
void dfs(Trie *pnt,int step)
{
    int start = dir[numarr[step]];
    int End = dir[numarr[step]+1];
    Trie *tmp = pnt;
    for(int i = start;i < End;i++)
    {
        if(tmp -> son[i] == NULL)
            continue;
        k++;//k表示当前的深度
        str[k] = i + base;
        if(tmp -> son[i] -> num > Max[k])//如果最大则更新答案
        {
            Max[k] = tmp -> son[i] -> num;
            str[k+1] = 0;
            strcpy(ans[k],str);
        }
        if(k != len-1)
            dfs(tmp->son[i],step+1);
        k--;
    }
}
int main()
{
    int T;
    char input[MAXN];
    scanf("%d",&T);
    for(int i = 1;i <= T;i++)
    {
        scanf("%d",&n);
        Trie *tree = NewTrie();
        for(int j = 1;j <= n;j++)
        {
            scanf("%s %d",input,&p);
            Insert(tree,input,p);
        }
        scanf("%d",&m);
        printf("Scenario #%d:\n",i);
        while(m--)
        {
            scanf("%s",numarr);
            len = strlen(numarr);
            len--;
            k = -1;
            memset(Max,-1,sizeof(Max));///
            dfs(tree,0);
            int w;
            for(w = 0;w < len;w++)
            {
                if(Max[w]!=-1)
                {
                    printf("%s\n",ans[w]);
                }
                else
                    break;
            }
            for(int j = w;j < len;j++)
                printf("MANUALLY\n");
            printf("\n");
        }
        printf("\n");
    }
    return 0;
}




独立完成项目-----T9输入法模拟器 本来这是老师给我们尖子小组三个人的一个合作挑战项目 但是我自己想了想 结构和原理按我的思路应该是可以行的通的 和他们俩住的远 也没得商量 思路上来就自己搞完了 项目名:手机T9输入法模拟器 参加人员:小枪 开发平台:window XP 开发工具:visual studio 2005 , sqlserver 2005 重点要点:全程数据库操作语句 全部采用 执行存储过程 模拟手机拼音输入法 如:2建代表 “abc” 贯彻三层结构数据理念 按不同的组织成不同的拼音组合 再根据这些拼音组合查询数据库 列出所有符合按拼音组合的汉字 这个地方相对我们在校的学生应该是比较有挑战的 总结思路 主要的思路构造就是全局做一个list将当前的所有能拼出来的拼音组合存起来 按下一个按就把它全拆开挨个拼出新的组合 然后将全局的list再用我们新拼的组合来替换掉 替换前要记得清掉我们listviwe 里的所有字和拼音 我觉得难的地方在于那个返回 也就是退格 它要干的事就是返回我们的上一个步骤 这里我处理手段使用的是以前依稀记得的冒泡排序 和list的rmove 来挨个处理 先把前面按组成的所有拼音组合挨个拿出来退一个字符 然后把第一个和所有集合中所有的拼音组合相比 有相同的就去掉 集合中原先第2个组合就成了现在的第一个组合 再把它拿出来挨个比较... 想了好久 靠 确实有点抽象了 说都有点说不明白 真不知道我们那班同学怎么去理解 字库问题 :还有就是字库的问题 据我所知汉字字库大概几千字 还是多少个来着 要做模拟器就得先做字库 这就有点麻烦了 一个一个的添显然麻烦 我偷了个懒 做俩个表 第一个表是我们的汉字表 包含两个字段: 汉字字符 和 我们的拼音外 (因为一个拼音组合可能会有几十或上百的同音字) 第二个表就是我们的拼音表 这样查询的时候也简单 根据拼音父建直接可以查到这个拼音组合下所有的同音字 为了字库入库方便 我顺便还写了一个入库工具 呵呵 这个就比较简单了 输入流 把同一个拼音组合的汉字放一个文本中 然后把这个文本中这些汉字做成一个数组 加的时候等于说一次就加一个拼音组合的汉字 怎么样 思路还算可以吧 呵呵 字库未加完 我这里带上字库 自己加进去吧 呵呵这样应该可以交差了 在校学生: 小枪
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值