• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
ACM s1124yy
守りたいものが 強くさせること
博客园    首页    新随笔    联系   管理     

HDU 1671 Phone List (Trie·数组实现)

链接:http://blog.csdn.net/acvay/article/details/47089657

 

题意  给你一组电话号码  判断其中是否有某个电话是另一个电话的前缀

字典树的基础应用  可以先把所有电话存进Trie  标记每个电话的结束字符  然后再查询每个号码  看中途是否有结束标记  有的话就说明有号码是这个号码的前缀了

实际上  插入完成就能知道是否有号码是另一个号码的前缀了  假设A是B的前缀

若A在B之前插入  那么插入B的时候会遇到A的结束标记

弱A在B之后插入  那么A插入完成之后的结点还有非空的孩子结点

这样就只用在每次插入时判断就行了  可以省掉查询这一步

 

指针和动态内存分配实现字典更容易些  但在有多组样例的时侯不释放内存会导致MLE  释放内存又要多花费不必要的时间  可能导致TLE  所以用数组实现比较好

 

#include<cstdio>
#include<cstring>
using namespace std;
const int N = 10005;
char tel[N][12];
int trie[N * 10][10], L;
bool end[N * 10], flag;
void initTrie() {
    L = 1;
    memset(trie, 0, sizeof(trie));
    memset(end, 0, sizeof(end));
}
void _insert(char *s) {
    int r = 0, i = 0, j;
    while (s[i]) {
        if (end[r]) flag = false;
        j = s[i++] - '0';
        if (!trie[r][j])
            trie[r][j] = L++;
        r = trie[r][j];
    }
    for (int i = 0; i < 10; i++) {
        if (trie[r][i]) flag = 0;
        end[r] = 1;
    }
}
int main() {
    int T, n;
    scanf("%d", &T);
    while (T--) {
        initTrie();
        scanf("%d", &n);
        flag = true;
        for (int i = 0; i < n; ++i) {
            scanf("%s", tel[i]);
            _insert(tel[i]);
        }
        puts(flag ? "YES" : "NO");
    }
    return 0;
}
View Code

 

posted @ 2016-08-14 03:22  s1124yy  阅读(305)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3