电话列表问题

一 问题描述

给出一个电话号码列表,确定它是否一致,如果没有数字是另一个号码的前缀,则称为一致。假设电话目录列出了这些数字。

紧急 911

爱丽丝 97 625 999

鲍勃 91 12 54 26

在这种情况下,无法呼叫 Bob,因为只要您拨打了 Bob 的电话号码的前三位数字,中心就会将您的呼叫转接到紧急线路。所以这个列表不一致。

二 输入和输出

1 输入

输入的第一行给出一个单一的整数,表示测试用例的数目。每个测试用例开头 N,表示电话号码的数目,在单独的一行,接下来的 N 行,每行一个唯一的电话号码。

2 输出

对每个测试用例,如果列表一致,则输出“YES”,否则输出“NO”。

三 输入和输出样例

1 输入样例

2

3

911

97625999

91125426

5

113

12340

123440

12345

98346

2 输出样例

NO

YES

四 分析和设计

1 分析

本问题是前缀判断问题。可以用字典树解决。

2 设计

a 将每个字符串依次插入到字典树中。

b 插入过程中判断两种情况:如果字符串处理完毕,仍不空,说明该串是其它串的前缀;如果遇到单词结束标记,说明其它串是该串的前缀。这两种情况均返回true;

c 如果 ans=true,则输出 NO,否则输出 YES。

需要注意的是,在插入判断的过程中,即使发现不一致,也不可以立即停止,继续读入数据,不插入字典树即可。

五 代码

package com.platform.modules.alg.alglib.poj3630;

public class Poj3630 {
    public String output = "";

    private int maxn = 1005; // 最多 10000 个字符串,每个字符串最多 10 位
    private int maxz = 10; // 不同字符个数,例如数字10,小写字母26
    int trie[][];
    boolean end[]; // 标识单词结束
    int n; // 字符串数
    int tot; // 下标

    boolean insert(String s) { // 将字符串s插入到字典树中
        int len = s.length();
        int p = 1;
        for (int i = 0; i < len; i++) {
            int ch = s.charAt(i) - '0'; // 转换成数字
            if (trie[p][ch] == 0)
                trie[p][ch] = ++tot; // 记录下标
            else if (i == len - 1) // 字符串处理完毕,仍不空,说明该串是其它串的前缀
                return true;
            p = trie[p][ch];
            if (end[p])
                return true;
        }
        end[p] = true; // 标记单词结束
        return false;
    }

    public String cal(String input) {
        int T;
        boolean ans;
        String s;
        String[] line = input.split("\n");
        T = Integer.parseInt(line[0]);
        int count = 1;
        while (T-- > 0) {
            trie = new int[maxn][maxn];
            end = new boolean[maxn];
            tot = 1;
            ans = false;
            n = Integer.parseInt(line[count++]);
            for (int i = 1; i <= n; i++) {
                s = line[count++];
                if (ans)
                    continue;
                if (insert(s)) // 不能立即结束,仍要读取 n 个串
                    ans = true;
            }
            if (ans)
                output += "NO\n"; // 有前缀输出 NO
            else
                output += "YES\n";
        }
        return output;
    }
}

六 测试

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值