T9-智能拼音

牛客网 HDU 1298 T9
字典树用于存储字典中各单词以及权值(可能性),每个节点只存储字符和权值,这是最简单的一种情况。而实际上还可以存储是否为单词结尾,有多少单词用作前缀等。
输入:
hell 3
hello 4
idea 8
next 8
super 3
相同的前缀其权值相加,根据这个输入建立的字典树为:
这里写图片描述
对于按键盘上43556这几个数字,首先4对应ghi,hi都在字典树中存在,且i的权值为8,应该优先显示。然后3对应def,和hi组合有id、ie、if、hd、he、hf,其中只有he和id存在,且id的权值为8(根据d的权值),而he的权值为7,所以优先显示id。之后类推。

输入:
abyb 3
abye 13
aaza 4
建立的字典树为:
这里写图片描述
对于2292来说,当摁完229,aby的权值最大为16,而aaz的权值为4。当摁完最后一个2,abyb的权值为3,而aaza的权值为4,所以应该显示aaza。

代码:

import java.util.*;
import java.io.*;

import static java.lang.System.out;

public class Main {
    public Node root = null;//根节点
    public Main() {
        this.root = new Node();
    }
    public void insert(String str, int weight) {//插入单词,维护字典树的各节点权值
        Node cur = this.root;
        for (char c: str.toCharArray()) {
            int index = c - 'a';
            if (cur.son[index] == null) {
                cur.son[index] = new Node(c, weight);
            } else {
                cur.son[index].weight += weight;//权值相加
            }
            cur = cur.son[index];
        }
    }
    public Comparator<String> comparator = new Comparator<String>() {//用于PriorityQueue的接口实现,根据字符串前缀的权值比较,权值大的要排在队头
        @Override
        public int compare(String o1, String o2) {
            // TODO Auto-generated method stub
            int w1 = search(o1), w2 = search(o2);
            if (w1 > w2) return -1;//根据字符串前缀的权值比较,权值大的要排在队头,返回-1表名要排在前面,即靠近队头
            else if (w1 < w2) return 1;
            else return 0;
        }
    };
    PriorityQueue<String> queue = new PriorityQueue<>(comparator);
    LinkedList<String> list = new LinkedList<>();//普通队列,用广度优先遍历存储各种可能的组合
    public String[] map = {"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};

    public void out(String digit) {
        list.clear();
        list.add("");
        for (int i = 0; i < digit.length(); i++) {
            int index = digit.charAt(i) - '0';
            while (!list.isEmpty() && list.peek().length() == i) {
                String s = list.removeFirst();
                for (char c:map[index].toCharArray())
                    if (search(s + c) != 0) list.add(s + c);//如果在字典树中存在,就加入普通队列
            }
            queue.clear();
            queue.addAll(list);//将普通队列的元素加入到PriorityQueue,让PriorityQueue自动帮我们找到权值最大的那个前缀,我们就不用自己手动写代码去找了
            if (!queue.isEmpty()) System.out.println(queue.peek());
            else System.out.println("MANUALLY");
        }
    }

    public int search(String string) {//返回该前缀的权重
        Node cur = this.root;
        for (char c: string.toCharArray()) {
            int index = c - 'a';
            if (cur.son[index] == null) return 0;
            else cur = cur.son[index];
        }
        return cur.weight;//权重是最后一个字符的权重
    }

    public static void main(String[] args) throws Exception{//读取输入并产生输出
    //还需要优化,因为不能将下面这些代码放在主方法里,而应该另外封装一个读取输入并产生输出的方法
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
        int scenario = Integer.parseInt(bufferedReader.readLine());
        for (int i = 1; i <= scenario; i++) {
            Main t = new Main();
            out.println("Scenario #" + i + ":");
            int createWord = Integer.parseInt(bufferedReader.readLine());
            for (int j = 0; j < createWord; j++) {
                String[] data = bufferedReader.readLine().split(" ");
                t.insert(data[0], Integer.parseInt(data[1]));
            }
            int intelligent = Integer.parseInt(bufferedReader.readLine());
            for (int k = 0; k < intelligent; k++) {
                String s = bufferedReader.readLine();
                t.out(s.substring(0, s.length() - 1));
                out.println();
            }
            out.println();
        }
    }
}

class Node {//节点类
    public Node[] son;//每个节点有26个子节点,只考虑小写字母的情况
    public int weight;//权值
    public char value;//存放的字符

    public Node () {
        son = new Node[26];
    }
    public Node(char value, int weight) {
        son = new Node[26];
        this.value = value;
        this.weight = weight;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值