HDU 1671 Phone List(字典树)

旧城冷巷雨未停 提交于 2019-11-26 16:00:58

- HDU 1671 -

Phone List

Time Limit: 3000/1000 MS (Java/Others) | Memory Limit: 32768/32768 K (Java/Others)

题意:

给定一个整数 t ,表示测试案例数,每个测试案例给定一个整数 n ,接下来输入 n 行号码,判断这些号码中是否有某个号码是另一个号码的前缀,若有,则输出‘NO’,否则,输出’YES’。

数据范围:

1 <= t <= 40, 1 <= n <= 10000.

解题思路:

字典树

本题用字典树的常规做法即可解出,但有一点要注意,那就是后来输入的号码可能是前面某个号码的前缀,所以在用字典树来解题之前,要先给每组的所有号码按长短排一下序,短的在前,长的在后,这样就能保证后面判断的号码不可能是前面已判断的号码的前缀。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <stack>
#include <queue>
#include <vector>
#include <map>
using namespace std;
#define INF 0x3f3f3f
#define zero 1e-7

typedef long long ll;
const int N=1e5;
int tree[N][11];
bool endd[N];
int k;

struct node {
    char s[15];
    int len;
};

bool cmp(node x, node y) {
    return x.len<y.len;
}

void init() {
    k=0;
    memset(tree, 0, sizeof(tree));
    memset(endd, false, sizeof(endd));
    return ;
}

bool judge(char *s) {
    int len=strlen(s);
    int p=0;
    bool flag=true;
    for(int i=0; i<len; i++) {
        int c=s[i]-'0';
        if(!tree[p][c])
            tree[p][c]=++k;
        p=tree[p][c];
        if(endd[p]) flag=false;
    }
    endd[p]=true;
    return flag;
}

int main() {
    int t, n;
    scanf("%d", &t);
    while(t--) {
        init();
        scanf("%d", &n);
        bool flag=true;
        node number[10005];
        for(int i=0; i<n; i++) {
            scanf("%s", number[i].s);
            number[i].len=strlen(number[i].s);
        }
        sort(number, number+n, cmp);//先给号码按长短排个序
        for(int i=0; i<n; i++) {
            if(!judge(number[i].s))
                flag=false;
        }
        if(flag) printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!